0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C言語】スライドパズルを作ってみた

Posted at

はじめに

こんにちは 高専1年、ロボコン部部員です
今回はC言語でスライドパズルを作ったので共有します
いつもより綺麗に作ることができたのでぜひ楽しんでいってください

プレイ画像

スライドパズル.png

コード解説

冒頭部分

マクロでは

  • ONE_SIDE → マップの一辺
  • DIFF→ マップのシャッフル回数

を表しています

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

#define ONE_SIDE 4
#define DIFF 10

int squared(int num);
void map_init(int *map);

void map_print(int map[ONE_SIDE * ONE_SIDE]);

void main_input(int *map);
int input(void);
int can_move(int *map,int ans);
void map_change(int *map,int ans);
int emp_cell_return(int map[ONE_SIDE * ONE_SIDE]);

int game_check(int map[ONE_SIDE * ONE_SIDE]);
void last_print(void);

conio.hというのはwindowsの環境依存ですのでお気を付けください

main関数

ゲームの基本進行関数の呼び出しを行います

int main(void){
	int map[ONE_SIDE * ONE_SIDE] = {0};
	map_init(map);
	do{
		map_print(map);
		main_input(map);
	}while(game_check(map) == 0);
	last_print();
	map_print(map);
	return 0;
}

squared関数

マクロで定義されたONE_SIDEを二乗するためだけに作られた関数です

int squared(int num){
	return num * num;
}

map_init関数

map配列の初期化を行います
ここでマクロ:DIFFの情報からマップをシャッフルします
見たことのない関数が呼び出されていますが
後で説明しますので心配ありません

void map_init(int *map){
	int init_i;
	int ans;
	int randnum[4] = {ONE_SIDE,-ONE_SIDE,1,-1};
	for(init_i=0; init_i<squared(ONE_SIDE); init_i++){
		map[init_i] = init_i+1;
	}
	map[squared(ONE_SIDE)-1] = 0;
	for(init_i=0; init_i<DIFF; init_i++){
		do{
			ans = randnum[rand()%4];
		}while(can_move(map,ans) == 0);
		map_change(map,ans);
	}
}

map_print関数

map配列からマップを表示します

void map_print(int map[ONE_SIDE * ONE_SIDE]){
	int print_i;
	printf("\n");
	for(print_i=0; print_i<squared(ONE_SIDE); print_i++){
		if(map[print_i] == 0){
			printf("[  ]");
		}else{
			printf("[%2d]",map[print_i]);
		}
		if(print_i%ONE_SIDE == ONE_SIDE-1){
			printf("\n");
		}
	}
	printf("\n");
}

main_input関数

実際に入力させる機構の軸となる関数です
can_move関数やmap_change関数はmap_init関数でも使う必要があったため、
入力の工程を入れるための、この関数が必要になった
のです

void main_input(int *map){
	int ans;
	do{
		ans = input();
	}while(can_move(map,ans) == 0);
	map_change(map,ans);
}

input関数

ここでプレイヤーに実際に入力してもらいます

int input(void){
	int ans = _getch();
	if(ans == 0 || ans == 0xE0){
		ans = _getch();
	}
	switch(ans){
		case 0x48:
			return -ONE_SIDE;
			break;
		case 0x50:
			return ONE_SIDE;
			break;
		case 0x4D:
			return 1;
			break;
		case 0x4B:
			return -1;
			break;
	}
}

_getch関数はconio.hによるもの、つまりはこちらもwindowsの環境依存です
お気を付けください

can_move関数

動かせる方向だったならば1を、そうでなければ0を返す関数です
emp_cell_return関数から得られる、『空白マス』の位置から判断します

int can_move(int *map,int ans){
	int emp_cell = emp_cell_return(map);
	int NG[4] = {0};
	int check_i;
	if(0<=emp_cell && emp_cell<=ONE_SIDE-1){
		NG[0] = ONE_SIDE;
	}else if(ONE_SIDE*(ONE_SIDE-1)<=emp_cell && emp_cell<=squared(ONE_SIDE)-1){
		NG[1] = -ONE_SIDE;
	}
	if(emp_cell%ONE_SIDE == 0){
		NG[2] = 1;
	}else if(emp_cell%ONE_SIDE == ONE_SIDE-1){
		NG[3] = -1;
	}
	
	for(check_i=0; check_i<4; check_i++){
		if(NG[check_i] == ans){
			return 0;
		}
	}
	return 1;
}

map_change関数

実際にmap配列を変更する関数です

void map_change(int *map,int ans){
	int emp_cell = emp_cell_return(map);
	map[emp_cell] = map[emp_cell - ans];
	map[emp_cell - ans] = 0;
}

emp_cell_return関数

『空白マス』の位置を返す関数です

int emp_cell_return(int map[ONE_SIDE * ONE_SIDE]){
	int check_i;
	for(check_i=0; check_i<squared(ONE_SIDE); check_i++){
		if(map[check_i] == 0){
			return check_i;
		}
	}
	return 0;
}

game_check関数

ゲームクリアしたかどうかを判断する関数です
クリアしたときには1を、そうでないときは0を返します

int game_check(int map[ONE_SIDE * ONE_SIDE]){
	int check_i;
	for(check_i=0; check_i<squared(ONE_SIDE)-1; check_i++){
		if(map[check_i] != check_i+1){
			return 0;
		}
	}
	return 1;
}

last_print関数

クリアしたことを表示するためだけの関数です
これ要るんでしょうか…?

void last_print(void){
	printf("\x1b[33mクリア!おめでと!!\x1b[0m\n");
}

さいごに

ここまで読んでくださりありがとうございました
参考になると嬉しいです

0
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?