中山清喬著『スッキリわかるC言語入門』という本を買って少し勉強してみた話です。

筆者(私)のスペック

C言語は完全初心者。Python、C#、JavaScriptは入門書を一冊づつ読みました。

C言語の学習を始めてみた理由

本屋でアルゴリズムの本を見てみたら、C言語で説明しているものが多かったので、それらの本の説明がわかる程度にはC言語を理解したいなーと思ったのがきっかけです。

『スッキリわかるC言語入門』について

これほど配慮の行き届いた親切な本ははじめてです。C言語は難しいイメージがありますが、手とり足とりな教え方ですごくわかりやすくて、いまのところ(260ページ目/751ページ)初心者の私でも普通について行けてます。C言語学習の1冊目におすすめできそうです。

章末には練習問題があって、「こういうプログラムを作りなさい」みたいな問題もあるんですが、それまでに習ったことだけを使ってどうにかできないかと考えるのがすごく楽しいです。

仮想環境は重い

本では開発環境の構築ガイドもあって、とりあえずその通りに構築してみました。 学習用にツールや設定を整えた仮想マシンが用意されていて、指示通りにインストールしていけばその仮想マシン上で開発できるようになります。 具体的にはVirtualBoxとVagrantというソフトウェアで仮想マシンを作ってlubuntuというOSを動かし、その環境内で開発する形になります。

ただ私のへっぽこPC(スペック:Core i3-530、メモリ4G、HDD、HD5670)にはだいぶ重いです。 仮想環境とWindowsを同時並行で操作するとフリーズしそうになります。 最近のPCならたぶん大丈夫じゃないかなとは思いますが。

そういうわけでWindowsでコンパイルできるように環境を構築してみようと思っています。ただ自力構築はハマりどころが多いらしいようなことが書いてあったのですんなりいくか不安です。

(追記)

全然すんなりいきませんでしたが、なんとか構築できました。記事→Windows Subsystem for Linux(WSL)とVisual Studio CodeでC言語の開発環境をつくった

数当てゲーム

以下は第7章(配列)の練習問題(7-4)で、数当てゲーム(ヒットアンドブロー)を作る問題の自分の解答のメモです(注:良いコードではないです)。こんな感じの練習問題がついているよってことで。

問題は、ランダムに生成された3桁の数を、一桁づつ予想して当てるゲームを作る、というものです。 桁と数字が一致していればヒット、違う桁に同じ数字があればブローとしてそれぞれカウントします。 3ヒットの場合は「正解です!」と表示しゲーム終了。それ以外は「続けますか?(1:続ける 0:終了)」と表示し、0なら終了、1なら数値入力まで戻るという処理を作ります。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>

typedef char String[1024];

int main(void){
	srand((unsigned)time(0UL));
	const int DIGITS=3;
	int answer[DIGITS];
	int input[DIGITS];

	printf("***数あてゲーム(レベル2)***\n%d桁の数を当ててください!\n", DIGITS);
	//answerの各桁にランダムな数字を代入(重複なし)
	for(int i=0;i<DIGITS;i++){
		answer[i]=rand()%10;
		//i+1桁目に代入する数字とすでに代入した桁の数字とを比較
		//して一致するものがなくなるまでランダム数字を上書きする
		for(int j=0; j<i; j++){
			while(answer[i]==answer[j]){
				answer[i]=rand()%10;
			}
		}
	}
	do{
		//カウンターを0に戻す
		int hit =0;
		int brow =0;
		//入力処理(0〜9以外の数字はやりなおし)←不完全
		for(int i=0;i<DIGITS;i++){
			do{
				printf("%d桁目の予想を0〜9の数字で入力してください:\n", i+1);
				String strInput;
				scanf("%s", strInput);
				input[i] = atoi(strInput);
			}while(input[i]<0||input[i]>9);
		}
		//位置も数字も一致ならhitに+1
		//位置は違うが同じ数字があればbrowに+1
		for(int i=0;i<DIGITS;i++){
			if(answer[i]==input[i]){
				hit++;
			}else{
				for(int j=0;j<DIGITS;j++){
					if(answer[i]==input[j]){
						brow++;
					}
				}
			}
		}
		printf("%dヒット! %dブロー!\n", hit, brow);
		//すべての桁で一致すれば正解→終了
		//不正解ならリトライするか終了するか選択
		if(hit==DIGITS){
			printf("正解です!\n");
			break;
		}else{
			printf("続けますか?(1:続ける 0:終了):\n");
			String retry;
			scanf("%s",retry);
			if(atoi(retry)==0){
				printf("正解は");
				for(int i=0; i<DIGITS;i++){
					printf("%d", answer[i]);
				}
				printf("でした!\n");
				break;
			}
		}
	}while(true);
	printf("ゲーム終了\n");
	return 0;
}

普通ヒットアンドブローは各桁の数字の重複はなしだった気がしたので、勝手に重複なしのゲームにしました。問題文をよく読んだら数字の重複についてはなにも指定がなかったので、重複ありにすればもう少し簡単に書けたみたいです。でも重複ありってゲームとして難しくないかな??

あとはゲームの桁数を変えたい時にDIGITSの数字を変えるだけで対応できるようにもしました。

ほかに数値入力の際に0~9以外を入力するとやり直しとなる処理も追加しました。でもこの処理は不完全で、単純に0未満と10以上の数字をはじいているだけです。文字を入力すると0になるし、小数を入力すると小数点以下が切り捨てになるので、これらの入力をはじくことができません。ここまでに出てきた知識ではいい解決法が思いつきませんでした。先のページで得られる知識に期待です。