C语言游戏跟电脑battle三子棋

Posted  Do

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言游戏跟电脑battle三子棋相关的知识,希望对你有一定的参考价值。

目录

三子棋

三子棋规则介绍

如何用c语言实现三子棋

基本思路

分部代码实现

游戏菜单

初始化棋盘

打印棋盘

玩家下棋

电脑下棋

判定胜负关系

 game()函数

总代码实现

game.h

game.c

test.c

玩游戏

总结


三子棋

三子棋算法有很多,这里仅是我个人的介绍,这种方法简单实现易于理解,特别适合新手实操。

三子棋规则介绍

三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。

如何用c语言实现三子棋

对于游戏实现的代码,我们最好分三个板块来写,而不是在一个源文件里面写。这里应该分类创建三个文件,test.c:游戏整体的逻辑。game.h:关于游戏相关函数的声明,头文件的包含。game.c:游戏相关函数的实现。

基本思路

  1. 创建游戏菜单,供用户选择玩游戏,还是退出游戏。

  2. 创建一个棋盘数组,并将它初始化。

  3. 打印一个棋盘。

  4. 玩家下棋(通过用户输入的坐标落子)

  5. 判定胜负关系。

  6. 电脑下棋(通过随机函数让它落子)

  7. 判定胜负关系。

  8. 游戏结束。

分部代码实现

游戏菜单

 

void menu()

	printf("********************\\n");
	printf("****** 1.play ******\\n");
	printf("****** 0.exit ******\\n");
	printf("********************\\n");
int main()

	int input = 0;
	printf("请选择:");
	srand((unsigned int)time(NULL));	//使用rand函数要调用srand
	do
	
		menu();
		scanf_s("%d", &input);
		switch (input)
		
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default :
			printf("输入错误,请重新选择!\\n");
			break;

		

	 while (input);
	return 0;
	

这里涉及到用户的选择,所以需要把主函数部分展现给大家看,利用do while语句实现游戏的重复,使用switch语句接收用户的选择,选择1则进入game()函数开始玩游戏,选择0则退出游戏,如果未按要求输入就重新选择,这里的条件设置为input非常巧妙,只有输入0才会退出循环。

初始化棋盘

void Initboard(char board[ROW][COL], int row, int col)		//初始化棋盘函数

	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	
		for (j = 0; j < col; j++)
		
			 board[i][j] = ' ';	//初始化棋盘为空格
		
	

棋盘可以看成一个数组,将棋盘初始化即利用for循环将棋盘数组每个元素初始化为空格。

打印棋盘

void Displayboard(char board[ROW][COL], int row, int col)		//打印棋盘函数
	//打印是无法将字符和下划线同时打印,只能分开.这里的思想是将字符和竖线看成一个整体,再将下滑线和竖线看成一个整体。
	//一个下划线代表一个空格,
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	
		for (j = 0; j < col; j++)
		   //打印一行
			printf(" %c ",board[i][j]); //将字符加竖线作为一个整体,分开打印
			if (j < col-1)
			
				printf("|");	//最后一列不用打印竖线
			
		
		printf("\\n");//记得每打印一行就换行
		//打印多行
		if (i < row-1)	//最后一行不打印下划线,不是最后一行都要打印
		
			int j = 0;
			for (j = 0; j < col; j++)
			
				printf("___");
				if (j < col-1)
				
					printf("|");
				
			
			printf("\\n");
		
	

下面我们来看看打印出来的棋盘:

这里有什么不懂得可以看我代码里的注释,解释的非常详细,我就不另外解释了。

玩家下棋

void Playerboard(char board[ROW][COL], int row, int col)		//玩家下棋

	int x = 0;
	int y = 0;
	while (1)
		//每次输入坐标下棋是一个循环,所以用while
		printf("玩家下棋,请输入坐标:\\n");
		
		scanf_s("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)		//判断坐标合法性
		
			if (board[x - 1][y - 1] == ' ')		//如果坐标没被占用,玩家输入的坐标与数组元素下标相差1
			
				board[x - 1][y - 1] = '*';
				break;  //玩家每下完一次要退出循环
			
			else
			
				printf("坐标被占用请重新输入!\\n");		//输入错误,没有break,就返回循环
			
		
		else
		
			printf("坐标不合法请重新输入!\\n");
		
		
	

这里有两个关键点:

(1)确定坐标的合法性,用户输入的坐标不能超过数组下标。

(2)判断坐标有没有被占用,如果没有被占用则玩家下棋,我把这里玩家下的棋为'*'号。

电脑下棋

void Computerboard(char board[ROW][COL], int row, int col)		//电脑下棋

	printf("电脑下棋:\\n");
	while (1)
	
	

		//要使电脑下棋合法即让随机数模坐标,其范围肯定不超过行和列
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')		//这里x和y不用减1,因为x和y的值不会等于行和列的数值
		
			board[x][y] = '#';
			break;		//电脑下完棋要退出循环,让玩家下棋
		

	

让电脑下棋则比较简单,使用rand随机函数即可,但这里要注意的是使用rand函数必须在主函数调用srand。

判定胜负关系

如果玩家赢则返回‘*’号,如果电脑赢则返回‘#’号,平局返回‘Q’。

判定是否平局:

int Isfull(char board[ROW][COL], int row, int col)

	int i = 0;
	
	for (i = 0; i < row; i++)
	
		int j = 0;
		for (j = 0; j < col; j++)
		
			if (board[i][j] == ' ')
			
				return 0;	//没满,返回0,与后面的字符ret对应,字符ret就返回c;
			
		
	
	return 1;	//当所有棋盘都遍历完之后没有空格则表示满了,返回1;与后面Iswin函数里面的ret返回值对应

判定胜负:

char Iswin(char board[ROW][COL], int row, int col)		//判断胜负函数

	int i = 0;
	for (i = 0; i < row; i++)		//判断三行
	
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		
			return board[i][1];		//返回*号则玩家赢,返回#号则电脑赢,不用另外判断
		
	
	for (i = 0; i < col; i++)		//判断三列
	
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
		
			return board[1][i];
		
	
	//判断两条对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	
		return board[1][1];
	
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
	
		return board[1][1];
	
	//Isfull函数判断平局,这里设计整型ret返回值与game()里的字符ret(用于接收iswin字符返回值判断输赢)对应
	int ret = Isfull(board, ROW, COL);		//这里的ret用来判断是否平局,如果返回1则返回Q,与前面的char ret对应,表示平局,不是返回1则返回c,游戏继续;

	if (ret == 1)
	
		return 'Q';
	
	return 'C';

 game()函数

void game()

	char board[ROW][COL];
	Initboard(board, ROW, COL);
	Displayboard(board, ROW, COL);
	char ret = 0;	//接收游戏返回的值

	while (1)
	
		Playerboard(board, ROW, COL);//玩家下棋
		Displayboard(board, ROW, COL);	//打印棋盘
		ret = Iswin(board, ROW, COL);	//判断是否赢
		if (ret != 'C')
		
			break;		//不是c则退出循环
		
		Computerboard(board, ROW, COL);	//电脑下棋
		Displayboard(board, ROW, COL);	//打印棋盘
		ret = Iswin(board, ROW, COL);	//判断电脑赢
		if (ret != 'C')		
		
			break;	//跳出循环,不下了
		
	
    if (ret == '*')
	
		printf("玩家赢了!\\n");
	
	else if (ret == '#')
	
		printf("电脑赢了!\\n");
	
	else
	
		printf("平局!\\n");
	
	Displayboard(board, ROW, COL);



game()函数是游戏的整体模型,包含了菜单打印,棋盘初始化,打印棋盘,玩家下棋,电脑下棋以及判定胜负这些函数的调用,这些函数一步一步实现以保证整个游戏的进行。这里要注意的是玩家和电脑下完棋后都要一一判定胜负。

总代码实现

这里写在一起的话不便于理解和修改,所以我分了三个部分:

game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 3
#define COL 3

void Initboard(char board[ROW][COL], int row, int col);
void Displayboard(char board[ROW][COL], int row, int col);
void Playerboard(char board[ROW][COL], int row, int col);
void Computerboard(char board[ROW][COL], int row, int col);
char Iswin(char board[ROW][COL], int row, int col);

game.c

#include"game.h"
void Initboard(char board[ROW][COL], int row, int col)		//初始化棋盘函数

	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	
		for (j = 0; j < col; j++)
		
			 board[i][j] = ' ';	//初始化棋盘为空格
		
	

void Displayboard(char board[ROW][COL], int row, int col)		//打印棋盘函数
	//打印是无法将字符和下划线同时打印,只能分开.这里的思想是将字符和竖线看成一个整体,再将下滑线和竖线看成一个整体。
	//一个下划线代表一个空格,
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	
		for (j = 0; j < col; j++)
		   //打印一行
			printf(" %c ",board[i][j]); //将字符加竖线作为一个整体,分开打印
			if (j < col-1)
			
				printf("|");	//最后一列不用打印竖线
			
		
		printf("\\n");//记得每打印一行就换行
		//打印多行
		if (i < row-1)	//最后一行不打印下划线,不是最后一行都要打印
		
			int j = 0;
			for (j = 0; j < col; j++)
			
				printf("___");
				if (j < col-1)
				
					printf("|");
				
			
			printf("\\n");
		
	

void Playerboard(char board[ROW][COL], int row, int col)		//玩家下棋

	int x = 0;
	int y = 0;
	while (1)
		//每次输入坐标下棋是一个循环,所以用while
		printf("玩家下棋,请输入坐标:\\n");
		
		scanf_s("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)		//判断坐标合法性
		
			if (board[x - 1][y - 1] == ' ')		//如果坐标没被占用,玩家输入的坐标与数组元素下标相差1
			
				board[x - 1][y - 1] = '*';
				break;  //玩家每下完一次要退出循环
			
			else
			
				printf("坐标被占用请重新输入!\\n");		//输入错误,没有break,就返回循环
			
		
		else
		
			printf("坐标不合法请重新输入!\\n");
		
		
	


void Computerboard(char board[ROW][COL], int row, int col)		//电脑下棋

	printf("电脑下棋:\\n");
	while (1)
	
	

		//要使电脑下棋合法即让随机数模坐标,其范围肯定不超过行和列
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')		//这里x和y不用减1,因为x和y的值不会等于行和列的数值
		
			board[x][y] = '#';
			break;		//电脑下完棋要退出循环,让玩家下棋
		

	

int Isfull(char board[ROW][COL], int row, int col)

	int i = 0;
	
	for (i = 0; i < row; i++)
	
		int j = 0;
		for (j = 0; j < col; j++)
		
			if (board[i][j] == ' ')
			
				return 0;	//没满,返回0,与后面的字符ret对应,字符ret就返回c;
			
		
	
	return 1;	//当所有棋盘都遍历完之后没有空格则表示满了,返回1;与后面Iswin函数里面的ret返回值对应

char Iswin(char board[ROW][COL], int row, int col)		//判断胜负函数

	int i = 0;
	for (i = 0; i < row; i++)		//判断三行
	
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		
			return board[i][1];		//返回*号则玩家赢,返回#号则电脑赢,不用另外判断
		
	
	for (i = 0; i < col; i++)		//判断三列
	
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ')
		
			return board[1][i];
		
	
	//判断两条对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	
		return board[1][1];
	
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ')
	
		return board[1][1];
	
	//Isfull函数判断平局,这里设计整型ret返回值与game()里的字符ret(用于接收iswin字符返回值判断输赢)对应
	int ret = Isfull(board, ROW, COL);		//这里的ret用来判断是否平局,如果返回1则返回Q,与前面的char ret对应,表示平局,不是返回1则返回c,游戏继续;

	if (ret == 1)
	
		return 'Q';
	
	return 'C';


test.c

#include<stdio.h>
#include"game.h"
void menu()

	printf("********************\\n");
	printf("****** 1.play ******\\n");
	printf("****** 0.exit ******\\n");
	printf("********************\\n");

void game()

	char board[ROW][COL];
	Initboard(board, ROW, COL);
	Displayboard(board, ROW, COL);
	char ret = 0;	//接收游戏返回的值

	while (1)
	
		Playerboard(board, ROW, COL);//玩家下棋
		Displayboard(board, ROW, COL);	//打印棋盘
		ret = Iswin(board, ROW, COL);	//判断是否赢
		if (ret != 'C')
		
			break;		//不是c则退出循环
		
		Computerboard(board, ROW, COL);	//电脑下棋
		Displayboard(board, ROW, COL);	//打印棋盘
		ret = Iswin(board, ROW, COL);	//判断电脑赢
		if (ret != 'C')		
		
			break;	//跳出循环,不下了
		
	
    if (ret == '*')
	
		printf("玩家赢了!\\n");
	
	else if (ret == '#')
	
		printf("电脑赢了!\\n");
	
	else
	
		printf("平局!\\n");
	
	Displayboard(board, ROW, COL);




int main()

	int input = 0;
	printf("请选择:\\n");
	srand((unsigned int)time(NULL));	//使用rand函数要调用srand
	do
	
		menu();
		scanf_s("%d", &input);
		switch (input)
		
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default :
			printf("输入错误,请重新选择!\\n");
			break;

		

	 while (input);
	return 0;
	

玩游戏

让代码跑起来,我来跟电脑交交手:

轻而易举战胜电脑,哈哈。还挺好玩的,大家有兴趣的话可以玩玩,或者你来告诉我怎么让电脑永远赢不了,嘻嘻。

总结

三子棋游戏考验了我们对数组的理解和运用,对循环分支语句的运用,关键是要理清思路,一步一步实现,像这种这么长的代码,我们最好是写完一部分就去运行一下,以防到最后出现错误很难去找。

本期文章就到这,希望能给大家带来帮助,那怕是一点点也好,我都非常高兴能帮助到大家,你们的认可是对我最大的帮助,你们的一键三连是我的动力。最后感谢大家的阅读,如有不足敬请谅解,欢迎大家批评指正!

 

 

以上是关于C语言游戏跟电脑battle三子棋的主要内容,如果未能解决你的问题,请参考以下文章

C语言初阶《三子棋》

三子棋游戏C语言版

C语言的三子棋

三子棋游戏

三子棋(C语言实现)

C语言三字棋小游戏详解