【三子棋的编写思路,实现方式及其代码】

我受够了等待,你所谓的安排................................................................................................

文章目录

目录

文章目录

前言

一、模块化编程的介绍

二、游戏实现思路及功能模块的编写

2.1游戏菜单的实现

 2.2打印棋盘

1.二维数组的创建和初始化

2.棋盘分割线的打印

2.3玩家下棋和电脑下棋

 2.4判断输赢

三、功能函数的组装及测试模块的编写

四、三子棋小游戏

完整代码:

总结


前言

讲述了三子棋小游戏的实现思路和实现方法,希望能帮到大家,完整的代码在第四部分。也欢迎大家指正错误,谢谢啦!                                  


一、模块化编程的介绍

         三子棋游戏需要采用模块化编程方式来实现 :分为三子棋头文件模块(game.h)、功能模块(game.c)、测试模块(test.c)这三个模块分工合作。

         所以这里需要介绍一下模块化编程:把各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数的声明,其它.c文件想使用其中的代码时,只需要#include "XXX.h"文件即可。使用模块化编程可极大的提高代码的可阅读性、可维护性、可移植性等。

          而在三子棋游戏的实现中,我们只需要将需要用到的库函数头文件包含在三子棋头文件(game.h),其他文件文件只需要包含到编写的三子棋头文件即可。三子棋头文件(game.h)包含自定义函数的声明即可,不需要实现函数的功能和调用。而在三子棋功能文件中(game.c),将函数体实现即可。测试文件(test.c)则主要负责游戏界面和函数调用的代码实现。当我们需要写一个大的工程或者项目(包含几万行代码那种),检查代码和维护代码是相当困难的,而采用模块化编程的方式式,,大大提高检查的效率和可阅读性。而且,有许多开发框架和工具也提供了模块化的支持,以简化模块的创建、管理和使用。由此可见,模块化编程是一种相当便利的编程方式。

二、游戏实现思路及功能模块的编写

首先,我么们都知道三子棋游戏,也被称为井字游戏(Tic-Tac-Toe),是一种简单的策略棋类游戏。它通常在一个3x3的方格棋盘上进行,两个玩家交替在空格内放置自己的标记,一般是一个玩家使用"X"标记,另一个玩家使用"O"标记。

游戏的目标是使自己的标记在水平、垂直或对角线上连成一条直线,先达到这个目标的玩家获胜。如果棋盘填满而没有任何一方连成一条线,则为平局。

而要编写三子棋游戏,就需要把其中一名玩家替换为电脑,从而进行编写。

1.编写函数实现供玩家选择的游戏菜单。

2.利用二维数组打印下棋的棋盘。

2.1游戏菜单的实现

在玩游戏的过程中,需要给玩家选择的权利,即玩家能够选择是进行游戏还是退出游戏,所以我们需要编写一个函数来实现这个功能,函数内部只采用了简单的打印功能,当我们需要是直接调用该函数即可。

代码展示:

void menu()
{
	printf("*********************\n");
	printf("**** 请选择操作  ****\n");
	printf("****  .1--play.  ****\n");
	printf("****  .0--exit.  ****\n");
	//printf("*****************\n");
	printf("*********************\n");
}

效果图:

 2.2打印棋盘

1.二维数组的创建和初始化

玩家在选择进入游戏后,应首先将游戏过程中需要用到的棋盘打印出来,想要实现这一目的,就要搞清楚三子棋游戏的本质——其实就是“二维数组”,可由3x3的方格棋盘轻松地联想到二维数组里的“行”和“列”那么关键在于这个二维数组里的元素是什么,在游戏开始时棋盘上是没有棋子的所以二维数组里的元素应该是“ ”(空格),所以我们需要创建一个二维数组,并将其内置元素初始化为空格。

1.注:这里的初始化部分我们应该用一个函数来写,因为每进行一次新的游戏都要进行一次初始化,也就是清空棋盘。

创建部分(ROW,COL为二维数组的行和列):

2.注:这里并没有直接把二维数组的行和列规定写死成3行3列,而是用#define定义的常量ROW和COL来代替,这样更方便后续的维护和修改。#define定义的这部分应该在三子棋的头文件部分完成。同样的功能模块里的函数在编写前也应在头文件模块中提前声明。

char board[ROW][COL] = { 0 };

初始化部分可以采用两层for循环的嵌套也可以用memset函数:

//for循环的嵌套:
void InitBoard(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++)
		{
		     board[i][j] = ' ';
		}
	}
}
//memset函数:memset(&board[0][0], ' ', row*col*sizeof(board[0][0]));

2.棋盘分割线的打印

这样棋盘的基础部分就设置好了,只需要将其打印出来就好了,同初始化部分相同,该部分也应写成函数形式(因为这部分也是重复性动作,写成函数形式方便调用)但是如果你再用两个for循环嵌套打印这个二维数组,会发现什么也打印不出来,这是因为数组的元素是空格,显示在电脑屏幕上什么也看不到,所以接下来要做的是,将棋盘的分割线打印出来。

先上代码1.(图中有解释):

void DisplayBoard(char board[ROW][COL], int row, int col)//传参,二维数组及其行和列
{
	int i = 0;
	int j = 0;
//两层for循环打印“ ”(空格)和“|”将(“ ”和“|”)看成一组内容进行打印
	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 < col; j++)
			{
				printf("---");
				if (j < col - 1)//打印完两组(“ ”和“|”)时应在打印一个空格而不打印“|”才能达到#棋盘的目的。
				{
					printf("|");
				}

			}
		}
		printf("\n");


		
	}
}

效果图:

到这里棋盘的打印就算成功了。

看到这里可能会对上面的代码1.产生疑问因为完全可以简单点完成

代码2.:

void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    	printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
		if(i < row-1)
			printf("---|---|---\n");
	}
}

上述代码2.也可以完成,可是上述代码会把棋盘的宽度规定死,比较局限,如果把行数(ROW)改成5则会出现下面的情况:

而写成上述代码1.的形式就会显得更加实用和方便。 

2.3玩家下棋和电脑下棋

通过上述的操作,解决了棋盘的问题,下面就要进行玩家与电脑之间的下棋和对弈了。那么怎么实现玩家和电脑在棋盘上落子呢?首先我们知道棋盘上的空位上分布的有元素——“ ”(空格)所以我们可以通过将“ ”(空格)替换为玩家所执的子来完成“落子”这一功能,电脑落子也是如此。需要注意的是玩家下棋和电脑下棋应用两个函数来分装,并且这两个函数也应在头文件模块中声明假定玩家用“*”充当棋子,电脑用“#”来充当棋子。废话不多说了,看代码:

//玩家下棋
void SPlayGame(char board[ROW][COL],int row ,int col )
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	
		while (1)//使用循环的原因:防止玩家错误的下棋,循环到下棋正确为止
		{
			printf("请输入棋子坐标");
			scanf("%d %d", &x, &y);//输入棋子的坐标
			if (x >= 1 && x <= row && y >= 1 && y <= col)//保证棋子落在棋盘上
			{
                //【x-1】【y-1】指的是数组下标所以要减一
				if (board[x-1][y-1] = ' ')//判断落子的位置是否已经被下上了棋子
				{
					board[x - 1][y - 1] = '*';
					break;
				}
				else
				{
					printf("错误\n");
				}
			}
			else
			{
				printf("输入错误\n");
			}
			
		}
}
//电脑下棋
void CPlayGame(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("电脑下棋\n");
	while (1)//使用循环的原因:循环到电脑下棋正确为止
	{
		 x = rand() % row;//采用srand函数来生成随机数,并用生成的随机数取模,来确定棋子的坐标 
         y = rand() % col;//同时也能确保棋子能够落在棋盘上。
		if (board[x][y] == ' ')//判断落子的位置是否已经被下上了棋子

		{
			board[x][y] = '#';
			break;
		}
		
	}
}

效果图:

 2.4判断输赢

当玩家和电脑每次下完棋如何判断它们之间的胜负关系呢?首先玩家和电脑下棋会出现以下情况。玩家赢,电脑赢,棋盘铺满没分出胜负即平局,棋盘没铺满棋局继续。不妨编写一个函数来判断棋局进行情况:

1.函数返回值为“*”——玩家赢

2.函数返回值为“#”——电脑赢

3.函数返回值为“s”——平局

4.函数返回值为“k”——棋局继续

代码:

//判断棋盘是否被铺满,铺满返回1,没满返回0,该函数用来判断是否平局
int Full(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++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}		
		}
	}
	return 1;
}
//判断输赢的函数
char Win(char board[ROW][COL], int row, int col)
{
	int i = 0;
	for (i = 0; i < row; i++)
	{
        //1.当横着三颗棋子连成一条线获胜的情况
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
		{
			return board[i][0];//返回返回获胜的一方所执棋子
		}
	}
	for (i = 0; i < col; i++)
	{
        //2.当竖着三颗棋子连成一条线获胜的情况
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];//返回返回获胜的一方所执棋子

		}
	}
    //3.当左上角,中间,右下角三颗棋子连成一条线获胜的情况
	if (board[0][0] == board[2][2] && board[2][2] == board[1][1] && board[0][0] != ' ')
	{
		return board[0][0];//返回返回获胜的一方所执棋子
	}
    //4.当右上角,中间,左下角三颗棋子连成一条线获胜的情况

	if (board[0][2] == board[2][0] && board[2][0] == board[1][1] && board[1][1] != ' ')
	{
		return board[0][2];//返回返回获胜的一方所执棋子
	}
    //棋盘被铺满未决出胜负————平局的情况
	if (Full(board,row, col))
	{
		return 's';//返回平局所对应的值
	}
    //上述的if语句均不成立,说明是棋局未结束的情况
	return 'k';返回“继续”对应的值
}

注3.:图中的Full函数并不用在头文件模块中进行声明,因为它包含在函数Win中,而Win需要在头文件模块中进行定义。

效果图:

好了,写到这里三子棋这个小游戏的所有功能就全部写完了,接下来把他们组装到测试模块中就大功告成了。

三、功能函数的组装及测试模块的编写

这部分主要是把前面编写的各种功能进行组装:

//自己编写的头文件
#include "game.h"
//菜单函数
void menu()
{
	printf("*********************\n");
	printf("**** 请选择操作  ****\n");
	printf("****  .1--play.  ****\n");
	printf("****  .0--exit.  ****\n");
	//printf("*****************\n");
	printf("*********************\n");
}
//存放功能的game函数
void game()
{
    //创建二维数组
	char board[ROW][COL] = { 0 };
    //二维数据的初始化
	InitBoard(board, ROW, COL);
    //打印棋盘
	DisplayBoard(board, ROW, COL);
    //定义ret来接收Win函数的返回值
	char ret = 0;
	while (1)
	{
        //玩家下棋并打印下完后的棋盘
		SPlayGame(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
        //ret来接收Win函数的返回值
		ret = Win(board, ROW, COL);
        //用ret来判断棋局进行情况
		if (ret != 'k')//只要不是“继续”就终止循环,进而判断胜负情况
		{
			break;
		}
        //电脑下棋并打印下完后的棋盘
		CPlayGame(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
        //ret来接收Win函数的返回值
		ret = Win(board, ROW, COL);
		if (ret != 'k')//只要不是“继续”就终止循环,进而判断胜负情况
		{
			break;
		}
	}
    //根据对应的符号,判断胜负平局
	if (ret == '*')
	{
		printf("你赢了\n");
	}
	else if (ret == '#')
	{
		printf("你输了\n");
	}
	else if (ret == 's')
	{
		printf("平局\n");
	}
}
//主函数
int main()
{
定义input来存放玩家的选择
	int input = 0;
	srand((unsigned int)time(NULL));//用于生成随机数
	do//因为玩家如果选择1,也就是开始游戏,而每下完一局都要回到菜单部分让玩家进行选择,所以应写在循环里。
	{
		menu();//菜单函数
		printf("请选择:>");
		scanf("%d", &input);//玩家输入选择
        //选1和选0对应的结果不同所以用switch多分支语句
		switch(input)
		{
		case 1:
			game();//功能函数都组装在了game函数里面
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default://输入(1和0之外数字则重新输入)
			printf("重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

注4:图中代码中玩家和电脑下完棋分别要判断一下胜负的原因是:我们不知道玩家和电脑谁赢,也不清楚是在一局游戏当中下第几次棋赢得,所以不妨每下一次棋就判断一下胜负情况。

四、三子棋小游戏

到这里整个三子棋就写完了,下面看一下成果吧!

完整代码:

1.测试部分代码(源文件):

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
	printf("*********************\n");
	printf("**** 请选择操作  ****\n");
	printf("****  .1--play.  ****\n");
	printf("****  .0--exit.  ****\n");
	//printf("*****************\n");
	printf("*********************\n");
}
void game()
{
	char board[ROW][COL] = { 0 };
	InitBoard(board, ROW, COL);
	DisplayBoard(board, ROW, COL);
	char ret = 0;
	while (1)
	{
		SPlayGame(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = Win(board, ROW, COL);
		if (ret != 'k')
		{
			break;
		}
		CPlayGame(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		ret = Win(board, ROW, COL);
		if (ret != 'k')
		{
			break;
		}
	}
	if (ret == '*')
	{
		printf("你赢了\n");
	}
	else if (ret == '#')
	{
		printf("你输了\n");
	}
	else if (ret == 's')
	{
		printf("平局\n");
	}
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

2.功能模块代码(源文件):

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void InitBoard(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++)
		{
		     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)
		{
			for (j = 0; j < col; j++)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}

			}
		}
		printf("\n");


		
	}
}
void SPlayGame(char board[ROW][COL],int row ,int col )
{
	int x = 0;
	int y = 0;
	printf("玩家下棋\n");
	
		while (1)
		{
			printf("请输入棋子坐标");
			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("错误\n");
				}
			}
			else
			{
				printf("输入错误\n");
			}
			
		}
}
void CPlayGame(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;
		}
		
	}
}
int Full(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++)
		{
			if (board[i][j] == ' ')
			{
				return 0;
			}		
		}
	}
	return 1;
}
char Win(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][0] != ' ')
		{
			return board[i][0];
		}
	}
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
		{
			return board[0][i];
		}
	}
	if (board[0][0] == board[2][2] && board[2][2] == board[1][1] && board[0][0] != ' ')
	{
		return board[0][0];
	}
	if (board[0][2] == board[2][0] && board[2][0] == board[1][1] && board[1][1] != ' ')
	{
		return board[0][2];
	}
	if (Full(board,row, col))
	{
		return 's';
	}
	return 'k';

}

3.头文件部分代码(头文件):

 
#define ROW 3
#define COL 3
 
 
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
 
void InitBoard(char board[ROW][COL], int row, int col);
 
void DisplayBoard(char board[ROW][COL], int row, int col);

void SPlayGame(char board[ROW][COL],int row,int col);

void CPlayGame(char board[ROW][COL], int row, int col);

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

运行结果图:


总结

这样就完成了三子棋这样一个小游戏。


                               

.................................................................................................................宁愿没出息,求我别离开  

                                                                                                                          ————《倒带》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以回答这个问题。以下是一个简单的C语言实现单人三子游戏的代码: ```c #include <stdio.h> #include <stdlib.h> #define BOARD_SIZE 3 void init_board(char board[][BOARD_SIZE]); void print_board(char board[][BOARD_SIZE]); int make_move(char board[][BOARD_SIZE], int row, int col, char player_char); int check_win(char board[][BOARD_SIZE], char player_char); int main() { char board[BOARD_SIZE][BOARD_SIZE]; int row, col, win; char player_char = 'X'; init_board(board); print_board(board); while (1) { printf("\nPlayer %c's turn.\n", player_char); printf("Enter row number: "); scanf("%d", &row); printf("Enter column number: "); scanf("%d", &col); if (make_move(board, row, col, player_char)) { print_board(board); win = check_win(board, player_char); if (win) { printf("\nPlayer %c wins!\n", player_char); break; } player_char = (player_char == 'X') ? 'O' : 'X'; } else { printf("Invalid move. Try again.\n"); } } return 0; } void init_board(char board[][BOARD_SIZE]) { int i, j; for (i = 0; i < BOARD_SIZE; i++) { for (j = 0; j < BOARD_SIZE; j++) { board[i][j] = '-'; } } } void print_board(char board[][BOARD_SIZE]) { int i, j; printf("\n"); for (i = 0; i < BOARD_SIZE; i++) { for (j = 0; j < BOARD_SIZE; j++) { printf("%c ", board[i][j]); } printf("\n"); } } int make_move(char board[][BOARD_SIZE], int row, int col, char player_char) { if (row < 0 || row >= BOARD_SIZE || col < 0 || col >= BOARD_SIZE || board[row][col] != '-') { return 0; } board[row][col] = player_char; return 1; } int check_win(char board[][BOARD_SIZE], char player_char) { int i, j; int row_win, col_win, diag_win1, diag_win2; for (i = 0; i < BOARD_SIZE; i++) { row_win = 1; col_win = 1; for (j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != player_char) { row_win = 0; } if (board[j][i] != player_char) { col_win = 0; } } if (row_win || col_win) { return 1; } } diag_win1 = 1; diag_win2 = 1; for (i = 0; i < BOARD_SIZE; i++) { if (board[i][i] != player_char) { diag_win1 = 0; } if (board[i][BOARD_SIZE-1-i] != player_char) { diag_win2 = 0; } } if (diag_win1 || diag_win2) { return 1; } return 0; } ``` 这个程序实现了基本的单人三子游戏,并且包括了判断胜负的函数。您可以根据需要修改和扩展此代码

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值