C语言实现三子棋游戏含完整代码

2021-11-25

目录
  • 一、text.c源文件部分
    • 1、main函数部分
    • 2、game函数部分
  • 二、game.h头文件部分
    • 三、game.c源文件部分
      • 运行

         三子棋是大家小时候和同桌在纸上都玩过的简单小游戏,这个游戏我们在c语言中就可以实现。

        在这篇文章我推荐大家使用vs2013,vs2019,vs2022等的编译器。部分学校使用的vc6.0以及Devc++。前者是1998年推出的c语言编译器,在现在的win10或者win11的系统中并不兼容,可能会出现一些问题,后者也在2015年停更,这两款祖传c语言编译器并不推荐使用,但是如果你们学校考试需要使用或者有明确要求,那当我没说。

        首先,我们要先创建一个项目,常见三个文件分别是头文件game.h,源文件game.c,text.c。在这个game.h的头文件中我们放入函数的声明,定义常量以及头文件的引用,在text.c文件中我们写入游戏进行的程序,在game.c文件中我们写入实现游戏的函数。 

        一、text.c源文件部分

        1、main函数部分

        因为我们玩一把游戏肯定不过瘾,我们要多玩几把游戏,我们在text.c文件中的main函数里写入一个do while循环语句,实现多次进行游戏。然后我们在循环语句中写入一个menu函数用来打印菜单。然后我们要在键盘上输入一个值去判断是否进行游戏,这里使用一个switch分支。当使用者输入正确的输入值时开始进行游戏。这里使用一个game函数实现游戏流程。

        int main()
        {
        	int n = 0;
         
        	srand((size_t)time(NULL));
        	do
        	{
        		menu();//打印菜单
        		printf("请输入  ");
        		scanf("%d", &n);
        		switch (n)
        		{
        		case 1:game(); break;
        		case 0:printf("游戏结束\n"); break;
        		default:printf("输入错误,请重新输入!\n"); break;
        		}
        	} while (n != 0);
        	
        }

        main函数部分

        ​void menu()
        {
        	printf("******************************************\n");
        	printf("********         1.play          *********\n");
        	printf("********         0.exit          *********\n");
        	printf("******************************************\n");
        }

        menu函数部分

        2、game函数部分

        在game函数中我们要实现游戏的主要流程,首先我们要打印一个3*3的棋盘,大概是这样的。

        (在这里我们先把游戏的流程捋清楚,至于实现那些游戏步骤的函数我们放在后面game源文件部分去细说。)

         因为每个格子在游戏开始的时候都是空着的状态,而在玩家与电脑进行游戏中是要输入符号的,所以我们还要定义一个char型的二维数组,并初始化为‘  '。然后就是下棋阶段,我们要连续下很多次棋所以说这里使用一个while循环语句实现,这里可以写成一个死循环,当后面的函数判断到有玩家已经胜出或者平局的时候使用break跳出循环,因为不论是电脑还是玩家下棋后,我们要看到下到了哪里,所以说我们要在玩家和电脑下棋后面再打印一次棋盘。每个人在下完棋之后,我们要判断是否已经胜利所以我们使用条件语句来判断是否胜利,失败或是平局。在配合循环我们基本游戏流程已经写完了。

        void game()
        {
        	char board[ROW][COL];//定义一个二维数组。
        	initboard(board, ROW, COL);//初始化数组。
            printboard(board, ROW, COL);//打印棋盘。
         
        	while (1)
        	{
        		//玩家下棋
        		playerboard(board, ROW, COL);
        		//打印棋盘
        		printboard(board, ROW, COL);
        		//判断是否胜利
        		if (iswinboard(board, ROW, COL) == '*')
        		{
        			printf("玩家胜利\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == '#')
        		{
        			printf("电脑获胜\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == 'Q')
        		{
        			printf("平局\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		
         
        		//电脑下棋
        		computermove(board, ROW, COL);
        		//打印棋盘
        		printboard(board, ROW, COL);
        		//判断是否胜利
        		if (iswinboard(board, ROW, COL) == '*')
        		{
        			printf("玩家胜利\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == '#')
        		{
        			printf("电脑获胜\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == 'Q')
        		{
        			printf("平局\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        	}
        }

        game函数部分

        二、game.h头文件部分

        在头文件中我们需要对函数进行声明,定义常量。具体怎么实现可以看下面代码的注释。
        在这里我们棋盘的行列在头文件使用ROW和COL来定义是为了方便我们以后在更改棋盘大小时,更加容易,只用在头文件中更改,在下面我们也能看到有很多地方使用这两个常量。

        #pragma once
        //在game头文件里面去声明函数,定义常量。
        #include<stdio.h>
        #include<stdlib.h>
        #include<time.h>
         
        //定义常量
        #define ROW 3//这里通过更改ROW,COL的值来改变棋盘的大小
        #define COL 3//可以更改成为n*n的棋盘。
         
        //函数声明
        //打印棋盘
        void printboard(char board[ROW][COL], int row, int col);
         
        //初始化数组
        void initboard(char board[ROW][COL], int row, int col);
         
        //玩家下棋//二维数组进行函数传参时可以不用写行数
        void playerboard(char board[][COL], int row, int col); 
         
        //电脑下棋
        void computermove(char board[ROW][COL], int row, int col);
         
        //判断是否胜利
        char iswinboard(char board[ROW][COL], int row, int col);

        game.h部分

        三、game.c源文件部分

        还记得我们在text.c中使用了哪些函数吗?

        • 1、我们先要初始化二维数组
        • 2、打印棋盘
        • 3、玩家下棋
        • 4、电脑下棋
        • 5、判断胜利

        接下来的game.c文件就是要写入实现这几个步骤的函数。

        首先,初始化数组非常容易,两个for循环即可。

        //初始化数组元素
        void initboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, j = 0;
        	//先对数组进行赋值,因为是n*n的数组所以要赋值n*n次
        	//这里使用两个for循环来实现。
        	for (i = 0; i < row; i++)
        	{
        		for (j = 0; j < col; j++)
        		{
        			board[i][j] = ' ';
        		}
        	}
        }

        初始化数组元素函数

        然后是打印棋盘函数。

        在打印棋盘中我们要注意,需要打印一行数组,一行“---”符号。在每一行的最后“|”不打印。在最下面一行“---|---|---”不打印,在这里我们只需要去控制for循环条件即可实现,并不困难。

        //打印棋盘
        void printboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, 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)
        		{
        			for (j = 0; j < row; j++)
        			{
        				printf("---");
        				if (j < row - 1)
        				{
        					printf("|");
        				}
         
        			}
        		}
        		
        		printf("\n");
        		
        	}
        }

        然后是玩家下棋函数

        也就是对数组进行赋值,因为玩家不一定学过c语言,也不一定知道c语言中数组的下标是从0开始的,所以我们要对输入的坐标-1之后在进行数组的相关操作。这里可以写上一个死循环,当玩家下出非法坐标时提醒玩家重新下,当玩家下出正确时再break跳出。

        //玩家下棋函数
        void playerboard(char board[][COL], int row, int col)
        {
        	int x = 0, y = 0;
        	printf("请玩家下棋\n");
        	while (1)//这里可以写上一个死循环,当玩家下出非法坐标时提醒玩家重新下。
        			//当玩家下出正确时再break跳出。
        	{
        		printf("请输入坐标,请用空格隔开。    \n");
        		scanf("%d %d", &x, &y);
        		if (x >= 1 && x <= row && y >= 1 && y <= col)//判断玩家下棋坐标是否正确。
        		{
        			if (board[x-1][y-1] == ' ')
        			{
        				board[x-1][y-1] = '*';
        				break;
        			}
        			else
        			{
        				printf("坐标已被占用,请重新输入!");
        			}
        		}
        		else
        		{
        			printf("坐标非法,请重新输入!");
        		}
        	}
        }

        再然后是电脑下棋

        相较于玩家下棋电脑下棋就比较容易了,只用使用rand()%3随机生成0-2之间的值,再判断是否已被占用即可。

        //电脑下棋
        void computermove(char board[ROW][COL], int row, int col)
        {
        	int x = 0; 
        	int y = 0;
        	printf("电脑下棋:>\n");
        	while (1)
        	{
        		x= rand() % ROW;//随机取值如果放在循环外面则可能陷入死循环。
        		y= rand() % COL;
        		if (board[x][y] == ' ')
        		{
        			board[x][y] = '#';
        			break;
        		}
        	}
        }

        最后是判断是否胜利的函数

        这个比较长,但是基本就是if条件语句进行判断,分别判断行、列、对角线以及平局。如果胜利成立则返回已连成线的其中一个格中的符号即可,这样就不用再麻烦这判断到底是电脑赢还是玩家赢了。返回到text.c中再进行相应的输出。

        //判断是否胜利
        char iswinboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, j = 0, count = 0;
         
        	//判断行是否胜利
        	for (i=0;i<row;i++)
        	{
        		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        		{
        			return board[i][0];
        			break;
        		}
        	}
        	//判断列是否胜利
        	for (j = 0; j < col; j++)
        	{
        		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
        		{
        			return board[0][j];
        			break;
        		}
        	}
        	//判断对角线
        	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
        	{
        		return board[0][0];
        	}
        	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
        	{
        		return board[0][2];
        	}
         
        	//判断是否平局
        	for (i = 0; i < row; i++)
        	{
        		for (j = 0; j < col; j++)
        		{
        			if (board[i][j] == ' ')
        			{
        				count++;
        			}
        		}
        	}
        	if (count == 0)
        	{
        		return 'Q';
        	}
        	return 'C';
        }

        这样我们的一个三子棋游戏就写好了。你就可以发给朋友,或是自己私藏了。(steam是上不了了,自己玩玩算了。)

        运行

        最后全部代码放在这里

        game.h

        #pragma once
        //在game头文件里面去声明函数,定义常量。
        #include<stdio.h>
        #include<stdlib.h>
        #include<time.h>
         
        //定义常量
        #define ROW 3//这里通过更改ROW,COL的值来改变棋盘的大小
        #define COL 3//可以更改成为n*n的棋盘。
         
        //函数声明
        //打印棋盘
        void printboard(char board[ROW][COL], int row, int col);
         
        //初始化数组
        void initboard(char board[ROW][COL], int row, int col);
         
        //玩家下棋//二维数组进行函数传参时可以不用写行数
        void playerboard(char board[][COL], int row, int col); 
         
        //电脑下棋
        void computermove(char board[ROW][COL], int row, int col);
         
        //判断是否胜利
        char iswinboard(char board[ROW][COL], int row, int col);

        text.c

        #define _CRT_SECURE_NO_WARNINGS 1
        #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);//初始化数组。
            printboard(board, ROW, COL);//打印棋盘。
         
        	while (1)
        	{
        		//玩家下棋
        		playerboard(board, ROW, COL);
        		//打印棋盘
        		printboard(board, ROW, COL);
        		//判断是否胜利
        		if (iswinboard(board, ROW, COL) == '*')
        		{
        			printf("玩家胜利\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == '#')
        		{
        			printf("电脑获胜\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == 'Q')
        		{
        			printf("平局\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		
         
        		//电脑下棋
        		computermove(board, ROW, COL);
        		//打印棋盘
        		printboard(board, ROW, COL);
        		//判断是否胜利
        		if (iswinboard(board, ROW, COL) == '*')
        		{
        			printf("玩家胜利\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == '#')
        		{
        			printf("电脑获胜\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        		else if (iswinboard(board, ROW, COL) == 'Q')
        		{
        			printf("平局\n");
        			printf("**********    是否进行下一局    **********\n");
        			printf("\n");
        			break;
        		}
        	}
        }
        int main()
        {
        	int n = 0;
         
        	srand((size_t)time(NULL));
        	do
        	{
        		menu();//打印菜单
        		printf("请输入  ");
        		scanf("%d", &n);
        		switch (n)
        		{
        		case 1:game(); break;
        		case 0:printf("游戏结束\n"); break;
        		default:printf("输入错误,请重新输入!\n"); break;
        		}
        	} while (n != 0);
        	
        }

        game.c

        #define _CRT_SECURE_NO_WARNINGS 1
        #include"game.h"
         
        //初始化数组元素
        void initboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, j = 0;
        	//先对数组进行赋值,因为是n*n的数组所以要赋值n*n次
        	//这里使用两个for循环来实现。
        	for (i = 0; i < row; i++)
        	{
        		for (j = 0; j < col; j++)
        		{
        			board[i][j] = ' ';
        		}
        	}
        }
         
        //打印棋盘
        void printboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, 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)
        		{
        			for (j = 0; j < row; j++)
        			{
        				printf("---");
        				if (j < row - 1)
        				{
        					printf("|");
        				}
         
        			}
        		}
        		
        		printf("\n");
        		
        	}
        }
         
        //玩家下棋函数
        void playerboard(char board[][COL], int row, int col)
        {
        	int x = 0, y = 0;
        	printf("请玩家下棋\n");
        	while (1)//这里可以写上一个死循环,当玩家下出非法坐标时提醒玩家重新下。
        			//当玩家下出正确时再break跳出。
        	{
        		printf("请输入坐标,请用空格隔开。    \n");
        		scanf("%d %d", &x, &y);
        		if (x >= 1 && x <= row && y >= 1 && y <= col)//判断玩家下棋坐标是否正确。
        		{
        			if (board[x-1][y-1] == ' ')
        			{
        				board[x-1][y-1] = '*';
        				break;
        			}
        			else
        			{
        				printf("坐标已被占用,请重新输入!");
        			}
        		}
        		else
        		{
        			printf("坐标非法,请重新输入!");
        		}
        	}
        }
         
        //电脑下棋
        void computermove(char board[ROW][COL], int row, int col)
        {
        	int x = 0; 
        	int y = 0;
        	printf("电脑下棋:>\n");
        	while (1)
        	{
        		x= rand() % ROW;//随机取值如果放在循环外面则可能陷入死循环。
        		y= rand() % COL;
        		if (board[x][y] == ' ')
        		{
        			board[x][y] = '#';
        			break;
        		}
        	}
        }
         
        //判断是否胜利
        char iswinboard(char board[ROW][COL], int row, int col)
        {
        	int i = 0, j = 0, count = 0;
         
        	//判断行是否胜利
        	for (i=0;i<row;i++)
        	{
        		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
        		{
        			return board[i][0];
        			break;
        		}
        	}
        	//判断列是否胜利
        	for (j = 0; j < col; j++)
        	{
        		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[0][j] != ' ')
        		{
        			return board[0][j];
        			break;
        		}
        	}
        	//判断对角线
        	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
        	{
        		return board[0][0];
        	}
        	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != ' ')
        	{
        		return board[0][2];
        	}
         
        	//判断是否平局
        	for (i = 0; i < row; i++)
        	{
        		for (j = 0; j < col; j++)
        		{
        			if (board[i][j] == ' ')
        			{
        				count++;
        			}
        		}
        	}
        	if (count == 0)
        	{
        		return 'Q';
        	}
        	return 'C';
        }

        以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持北冥有鱼。

        《C语言实现三子棋游戏含完整代码.doc》

        下载本文的Word格式文档,以方便收藏与打印。