三子棋小游戏

史上最详细的手把手三子棋小游戏全教程来啦!!!!

不过在着手制作之前,我们首先要把逻辑理清楚, 三子棋首先得有个棋盘对吧,在C语言里面,我们就用一个二维数组来表示棋盘

1.首先对棋盘进行初始化

void init(void){  //初始化棋盘
	int i, j;
	for (i = 0; i <= 2; ++i)
	for (j = 0; j <= 2; ++j){
		g_chess[i][j] = ' ';
	}
}

2.初始化完了之后,我们就需要一个函数来把棋盘 打印在屏幕上

void printfchess(void){//打印棋盘
	int i;
	for (i = 0; i < 3; ++i){
		printf("    | %c | %c | %c |    \n", g_chess[i][0], g_chess[i][1], g_chess[i][2]);
		if (i<2)
			printf("    -------------\n");
	}
}

3.除了打印和初始化,我们还需要一个判定输赢,还有棋子是否已经满了的函数

判断输赢

int checkwinner(){
	int row, list;
	for (row = 0; row <= 2; ++row){
		for (list = 0; list <= 2; ++list){
			if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'O')
				return 2;//返回2是电脑赢
			if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'O')
				return 2;
			if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'X')
				return 1;//返回1是人赢
			if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'X')
				return 1;
		}
	if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'X')
		return 1;
	if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'X')
		return 1;
	if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'O')
		return 2;
	if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'O')
		return 2;
	}
}

 棋子满

int checkfull(){//检查是否已满
	int i;
	int j;
	for (i = 0; i <= 2; i++){
		for (j = 0; j <= 2; j++){
			if (g_chess[i][j] == ' ')
				return 4;
		}
	}
	return 3;
}

4.之后就是我们的重头戏了,一个playgame函数将上面的函数 涵盖进来并进行每一次的下棋

int playgame(){
	int row = 0, list = 0;
	int gameget = 0;
	int gamegot = 0;
	srand((int)time(0));
	while (1){
		gameget = rand() % 3;//不能直接让随机值作为下标不然调用的时候每次都获得一个新的值,
		//从而覆盖上一个应该用一个临时变量保存随机数的值
		gamegot = rand() % 3;
		if (g_chess[gameget][gamegot] != 'X' && g_chess[gameget][gamegot] != 'O'){
			g_chess[gameget][gamegot] = 'O';
			printf("\n请电脑下棋\n");
			printfchess();//打印棋盘
			break;
		}
	}
	if (checkwinner() == 2){   //一定要在下棋后检查,因为三子棋,是九个格子!!!
		printf("电脑获胜\n");
		return 0;
	}
	if (checkfull() == 3){
		printf("和棋\n");
		return 0;
	}
	while (1){
		printf("请玩家下棋,先行后列输入坐标\n");//玩家下棋
		scanf("%d %d", &row, &list);
		if (g_chess[row][list] == 'X' || g_chess[row][list] == 'O'){  //该if与下面的else if循序不能颠倒,否则会有逻辑错误
			printf("该地方已有棋子,请重新输入\n");
			continue;//如果输入不对则重来,直到进入下一条件判断
		}
		else if (row <= 2 && row >= 0 && list <= 2 && list >= 0){
			g_chess[row][list] = 'X';
			printf("\n");
			printfchess();//打印棋盘
			break;//易错点,不能用continue跳出循环,否则会导致while无限循环
		}
		else{
			printf("坐标不在棋盘内,请重新输入\n");
			continue;
		}
	}
	if (checkwinner() == 1){
		printf("玩家获胜\n");
		return 0;
	}
	if (checkfull() == 3){
		printf("和棋\n");
		return 0;
	}
}

5.最后将上面这一个个模块整合起来就是完整的三子棋代码了

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

char g_chess[3][3] = { 0 };

void init(void){  //初始化棋盘
	int i, j;
	for (i = 0; i <= 2; ++i)
	for (j = 0; j <= 2; ++j){
		g_chess[i][j] = ' ';
	}
}

int checkwinner(){
	int row, list;
	for (row = 0; row <= 2; ++row){
		for (list = 0; list <= 2; ++list){
			if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'O')
				return 2;//返回2是电脑赢
			if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'O')
				return 2;
			if (g_chess[row][0] == g_chess[row][1] && g_chess[row][0] == g_chess[row][2] && g_chess[row][0] == 'X')
				return 1;//返回1是人赢
			if (g_chess[0][list] == g_chess[1][list] && g_chess[0][list] == g_chess[2][list] && g_chess[0][list] == 'X')
				return 1;
		}
	if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'X')
		return 1;
	if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'X')
		return 1;
	if (g_chess[0][0] == g_chess[1][1] && g_chess[1][1] == g_chess[2][2] && g_chess[0][0] == 'O')
		return 2;
	if (g_chess[0][2] == g_chess[1][1] && g_chess[1][1] == g_chess[2][0] && g_chess[0][2] == 'O')
		return 2;
	}
}


int checkfull(){//检查是否已满
	int i;
	int j;
	for (i = 0; i <= 2; i++){
		for (j = 0; j <= 2; j++){
			if (g_chess[i][j] == ' ')
				return 4;
		}
	}
	return 3;
}

void printfchess(void){//打印棋盘
	int i;
	for (i = 0; i < 3; ++i){
		printf("    | %c | %c | %c |    \n", g_chess[i][0], g_chess[i][1], g_chess[i][2]);
		if (i<2)
			printf("    -------------\n");
	}
}

int playgame(){
	int row = 0, list = 0;
	int gameget = 0;
	int gamegot = 0;
	srand((int)time(0));
	while (1){
		gameget = rand() % 3;//不能直接让随机值作为下标不然调用的时候每次都获得一个新的值,
		//从而覆盖上一个应该用一个临时变量保存随机数的值
		gamegot = rand() % 3;
		if (g_chess[gameget][gamegot] != 'X' && g_chess[gameget][gamegot] != 'O'){
			g_chess[gameget][gamegot] = 'O';
			printf("\n请电脑下棋\n");
			printfchess();//打印棋盘
			break;
		}
	}
	if (checkwinner() == 2){   //一定要在下棋后检查,因为三子棋,是九个格子!!!
		printf("电脑获胜\n");
		return 0;
	}
	if (checkfull() == 3){
		printf("和棋\n");
		return 0;
	}
	while (1){
		printf("请玩家下棋,先行后列输入坐标\n");//玩家下棋
		scanf("%d %d", &row, &list);
		if (g_chess[row][list] == 'X' || g_chess[row][list] == 'O'){  //该if与下面的else if循序不能颠倒,否则会有逻辑错误
			printf("该地方已有棋子,请重新输入\n");
			continue;//如果输入不对则重来,直到进入下一条件判断
		}
		else if (row <= 2 && row >= 0 && list <= 2 && list >= 0){
			g_chess[row][list] = 'X';
			printf("\n");
			printfchess();//打印棋盘
			break;//易错点,不能用continue跳出循环,否则会导致while无限循环
		}
		else{
			printf("坐标不在棋盘内,请重新输入\n");
			continue;
		}
	}
	if (checkwinner() == 1){
		printf("玩家获胜\n");
		return 0;
	}
	if (checkfull() == 3){
		printf("和棋\n");
		return 0;
	}
}

int main(void){
	init();//初始化棋盘
	printf("游戏开始\n");
	while (1){
		if (playgame() == 0)
			break;
		//如果不出现胜利者或者和棋,则回到循环继续游戏
	}
	return 0;
}

最后一些容易 出错的地方进行 整理一下

1.判断胜利的 函数要放在和棋之前,否则最后一个子下的时候会将胜利给掩盖掉

2.一定要在电脑和人下子之后分别进行一次检查,因为三子棋只有九个格,如果在电脑和人都 下了子之后才统一进行判断的话讲无法判断最后一个子的情况(简单的说就是一个九个格子的棋盘内每次下两个子,然后统一判断人赢还是电脑赢,当下到第八个子时已经没有足够的空间让人和电脑都下一个子了)

3.在循环中时 要注意区分continue和break和细微差别

4. 随机种子不能放进循环内,因为 计算机运行速度极快,随机种子是截取时间作为伪随机运算的参数,放进循环内会导致随机种子不能有效 得到随机数

 还有一些 容易出错的地方我已经在代码的注释中说得很清楚了,希望对你 有所帮助( Φ ω Φ )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值