三子棋

Posted 快乐江湖

tags:

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

文章目录

一:三子棋游戏介绍

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

二:C语言实现三子棋

这里不采用拿出完整代码的方式,讲解每一部分代码是什么作用,我们从0开始,一步一步实现整个逻辑

(1)新建文件

整个游戏需要三个文件,第一个是头文件“chess.h”用于声明函数,宏定义等,第二个是“chess_achive.c”用于实现头文件中所声明函数的功能,第三个是"chess.c"用于控制整个游戏逻辑。

(2)逻辑流程

第一:先打印菜单,与用户对话
如下


但是这里有一个问题,如何如何让用户“挑选”选项,然后程序再进行对应操作呢。我们可以这样,使用变量input接受用户输入的数据,再用switch函数进行操作


第二:游戏函数
首先游戏函数大体上的逻辑如下

  1. 在现实生活中,我们下棋用的是棋子,但是在电脑上不可能有真的棋子。所以我们需要某种东西去代替它,最能想到的就是用符号,而符号是一个字符,所以我们可以建立一个字符数组去存储这些棋子。
    为了方便我们建立一个3×3的棋盘,所以字符数组也设置为相应大小,这里需要注意的一点是,为了整个游戏的可变性,不至于以后棋盘的大小只能是3×3,所以我们实现要在头文件中进行宏定义,以后改变棋盘大小时只需在此处更改

  2. 字符数组建立好之后,我们就要“洗牌”,意思就是让棋盘面清空,所谓清空实际意思就是字符数组每个字符都是空的。这一过程就不用详细叙述了
  3. 现实中的棋盘是能摸得着的,但是显示屏上棋盘却不是真的,或者说它就是不是棋盘,可以理解为打印出几条线,让棋子分割开来。所以这一步我们得设计一个函数去显示出棋盘,不止再这里要用,再后面电脑和人下棋的时候,也是需要下一步棋就显示棋盘的。
    我们的棋盘(3×3)样式基本就是下面这样:图中空白的位置就是棋子的落脚位置,线条就是棋子的分割线

    相应代码部分我们的思路是,打印一个数据,打印一条竖分界线,其中一个数据占用三列,一行打印完之后再打印下一行


这里稍稍美中不足的就是最后一列数据分界线被打印出来二路,显得很别扭,可以这样操作

  1. 接着就是电脑和玩家开始下棋

    所以要分别实现玩家下棋和电脑下棋的函数
    用户下棋时,让用户输入坐标以确定棋子,这里需要注意的一点是,用户不知道数组下标是从0开始的,所以用户认为第一个位置坐标为(1,1),但是实际上(0,0),所以在处理这一点时要注意转换
    用户输入坐标时有可能会造成非法输入,所以要用循环确保用户输入正确,同时想要落子就要确保落子的位置必须是空的。

    电脑下棋时一定是随机的,所以要使用到随机数。对于随机数有这样的三步,第一引入头文件“time.h”,第二利用时间戳时间随机种子,第三进行取余操作,确保随机数所取范围。
    随机数设好之后,电脑下棋就很好写了

  2. 重要的落子步骤完成之后,就需要注意一点,因为每一次落子有可能胜负就出来了。所以在用户或者是电脑下棋完成之后,立马就要对整个棋盘进行判断。我们编写一个判断输赢的函数,输赢无非有四种情况(玩家赢,电脑赢,平局即棋盘满了,继续),所以首先要判断棋盘是否满了,棋盘满了一定没有分出胜负,就是平局。棋盘没有满那就对其横竖斜进行判断


三:演示

玩家赢

电脑赢

平局

四:完整代码

头文件

#define COW 3
#define COL 3//定义这个棋盘的行和列
void Initboard(char board[COW][COL], int cow, int col);//初始化棋盘函数声明
void Displayboard(char board[COW][COL], int cow, int col);//打印骨架函数声明
void Playerboard(char board[COW][COL], int cow, int col);//玩家走
void Computerboard(char board[COW][COL], int cow, int col);//电脑走
//Iswin返回值为字符型,通过返回特定字符来判断输赢情况
/*
    1:返回“*”表示玩家赢
	2:返回“#”表示电脑赢
	3:返回“C”表示继续
	4:返回“Q”表示平局
*/
char Iswin(char board[COW][COL], int cow, int col);

函数实现文件


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "SanZiQi_head.h"
void Initboard(char  board[COW][COL], int cow, int col)//初始化棋盘

	for (int i = 0;i < cow;i++)
	
		for (int j = 0; j < col; j++)
		
			board[i][j] = ' ';
		
	

void Displayboard(char board[COW][COL], int cow, int col)//打印棋盘骨架(这里涉及到一些概念见笔记)

	int i = 0;
	for (i = 0; i < cow; i++)//先打印数据行和行分界线
	
		int j = 0;
		for (j = 0; j < col; j++)//打印数据行
		
			printf(" %c ", board[i][j]);//一个数据占三行,“ %c ”
			if (j < col - 1)//每打印一个数据,画一条数据分界线,其中为了美观最后一列的数据的分界线不用打印
				printf("|");
		
		printf("\\n");//打印完一行数据换一行
		if (i < cow - 1)//打印下一行之前,打印一条行分界线,为了美观最后一行的行分界线不用打印
		
			for (j = 0; j < col; j++)//打印行分界线
			
				printf("---");
				if (j < col - 1)
					printf("|");//打印行分界线的竖分界线,还是一样最后一列的数据分界线不用打印
			
			printf("\\n");//打印完一行行数据分界线
		

	

void Playerboard(char board[COW][COL], int cow, int col)//用户输入

	int x = 0;
	int y = 0;
	printf("你走:\\n");
	while (1)//用户输入的坐标可能会出现非法情况,所以要用循环,一旦出现非法,就再接受
	
		printf("请输入坐标\\n");
		scanf("%d%d", &x, &y);//接受用户坐标
		if (x >= 1 && x <= cow && y >= 1 && y <= col)//这里注意用户是不知道数组下标是从0开始的,所以我们判断的时候要考虑用户认为第一个坐标是1,1
		
			if (board[x - 1][y - 1] == ' ')//输入合法并且要输入的位置没有东西
			
				board[x - 1][y - 1] = '*';//那么就用一个“*”表示用户输入
				break;//一旦输入成功跳出循环,就该电脑输入了
			
			else
			
				printf("该位置已经被占用了\\n");
			

		
		else
		
			printf("输入越界,请重新输入\\n");//非法情况
		
	


void Computerboard(char board[COW][COL], int cow, int col)

	int x = 0;
	int y = 0;
	printf("电脑走\\n");
	while (1)//电脑也可能输入错误,所以也要循环
	
		x = rand() % cow;//这种方式能保证x取值为0,1,2,
		y = rand() % col;//这种方式能保证y取值为0,1,2,
		if (board[x][y] == ' ')
		
			board[x][y] = '#';//如果正确输入电脑的符号
			break;//输入完成跳出循环
		

	

int Isfull(char board[COW][COL], int cow, int col)//注意这个函数不用在头文件里声明,因为Iswin被声明了,Isfull在Iswin的本文件前面调用了

	int i = 0;
	int j = 0;
	for (i = 0; i < cow; i++)
	
		for (j = 0; j < col; j++)
		
			if (board[i][j] == ' ')
			
				return 0;//一旦找到空,表明棋盘没有满
			
		
	
	return 1;//执行到这说明满了


char Iswin(char board[COW][COL], int cow, int col)

		//判断输赢时,横三行,竖三列,和主副对角只要元素相同就代表某方赢,返回对应字符即可
	int i = 0;
	int j = 0;
	//判断横三行
	for (i = 0; i < cow; 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[1][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[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
	
		return board[1][1];
	
	   //以上用于判断电脑还是玩家赢
	   //接下来判断是否平局和继续
	if (1 == Isfull(board, COW, COL))//如果棋盘满了就表示平局
	
		return 'Q';
	
	return 'C';//没有赢,也没有平局那就继续




逻辑控制文件

#define _CRT_SECURE_NO_WARNINGS 1
#include "SanZiQi_head.h"
#include <stdio.h>



//本游戏用到game.c,game.h

void menu()//菜单

	printf("************三子棋对战游戏**************\\n");
	printf("***********1.play   0.exit***************\\n");
	printf("*****************************************\\n");


void game()

	char ret = 0;//接受字符,用于判断输赢情况
	char board[COW][COL] =  0 ;//建立一个二维数组,形式上看起来就像一个棋盘
	Initboard(board, COW, COL);//初始化棋盘,所有元素空格,看起来就像没有元素一样
	Displayboard(board, COW, COL);//打印棋盘骨架
	while (1)//电脑和玩家循环下棋
	
		Playerboard(board, COW, COL);//玩家先走
		Displayboard(board, COW, COL);
		//玩家走完立马判断情况
		ret = Iswin(board, COW, COL);//ret用于接受Iswin函数返回输赢的特征字符情况
		if (ret != 'C')//如果ret不是C,说明已经判断出输赢情况了,及立马跳出while,去判断情况
		
			break;
		
		Computerboard(board, COW, COL);//电脑再走
		Displayboard(board, COW, COL);
		ret = Iswin(board, COW, COL);
		if (ret != 'C')//如果ret不是C,说明已经判断出输赢情况了,及立马跳出while,去判断情况
		
			break;
		
	
	if (ret == '*')
	
		printf("你赢了\\n");
	
	else if (ret =='#')
	
		printf("电脑赢了\\n");
	
	else
	
		printf("平局\\n");
	



void test()//开始游戏

	srand((unsigned int)time(NULL));
	int input = 0;
	do
	
		menu();
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\\n");
			break;
		default:
			printf("请重新选择\\n");
			break;
		
	 while (input);



int main(void)

	test();
	return 0;


以上是关于三子棋的主要内容,如果未能解决你的问题,请参考以下文章

C语言初阶《三子棋》

C语言初阶《三子棋》

P1838 三子棋I

实现三子棋

三子棋初稿

这个三子棋,输了就要接受惩罚哦!