C语言实现三子棋

三子棋是一个大家都很熟悉的游戏,思路非常简单,用O代表电脑,X代表玩家。在程序员的眼里三子棋的实现和数组、函数等内容有着密不可分的关联。三子棋的棋盘我们都见过,坐标成对出现,二维数组就可以完美的解决。这里模块化的解决思想就凸显的十分重要,将要解决的问题封装成一个个函数,那我们具体分析三子棋具体要解决哪些问题?
首先得提供给用户菜单供选择,接下来得打印出它的棋盘界面,玩的过程电脑走一步人走一步,游戏具体怎样实现以及判断每一步接下来什么情况该继续走,大致分为六大部分。下面将分析每一部分以及它的具体实现。
1、头文件:使函数调用方便,程序更加整齐

#define _CRT_SECURE_NO_WARNINGS 1
#ifndef _THREE_CHESS_H_
#define _THREE_CHESS_H_
#include <stdio.h>
#include <windows.h>  
#include <time.h>
#pragma warning(disable:4996)
#define ROW 3
#define COL 3
void ShowUI(); //以下是函数声明
void Game();
void ComputerMove(char board[][COL], int row, int col);
void ShowBoard(char board[][COL], int row, int col);
char Judge(char board[][COL], int row, int col);
void PlayerMove(char board[][COL], int row, int col);
#endif

2、显示菜单函数:
这个函数非常简单,printf语句也十分明了。附录如下

void ShowUI()
{
	printf("##################################\n");
	printf("## 1. Play              2. Exit ##\n");
	printf("##################################\n");
	printf("Please Select:> ");
}

3、棋盘显示函数:(供game函数调用)
三子棋棋盘是一个九宫格(三行三列),首先打印列1、2、3,定义两个变量i和j分别控制行和列,只要i小于row,则打印i+1,循环条件为i<row,(row和col在都宏定义为3),就会打印出来行1、2、3.内层嵌套循环打印 | ,输出board[i][j],这样一个简单九宫格就打印出来了。

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

4、电脑下棋函数:(供game函数调用)
因为电脑是自动落子,所以得为电脑产生一个随机的 棋子二维数组下标值,使电脑随机落子,这个用srand((unsigned)time(NULL));(在game函数中将具体实现),此函数只需要随机生成行和列,让棋盘坐标去判断是不是等于空,如果等于空则用O填充,循环条件为真,因为每一步都要去随机生成行和列。

void ComputerMove(char board[][COL], int row, int col)
{
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = 'O';
			break;
		}
	}
}

5、用户下棋函数:(供game函数调用)
首先得从键盘输入坐标,判断输入的坐标是否合法,行和列都在3以内,则判定输入合法,如果用户输入的位置为空,则可以用X填充,否则重新输入。

void PlayerMove(char board[][COL], int row, int col)
{
	int x, y;
	while (1)
	{
		printf("Please Enter Your Pos(x,y):>  ");
		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] = 'X';
				break;
		   }
			else
			{
				printf("Enter Pos Is Not OK, Try Again!\n");
			}
		}
		else
		{
			printf("Enter Error, Try Again!\n");
		}
	}
}

6、具体玩游戏部分
先把棋盘初始化为空格,在这里不断去调用其它子函数,每调一次判断一次结果,共有四种可能,用switch语句实现,(电脑赢、玩家赢、平局、其它),如果有结果就break跳出,没有结果则继续进行游戏。
注释:memset是计算机中C/C++语言初始化函数。作用是将某一块内存中的内容全部设置为指定的值, 这个函数通常为新申请的内存做初始化工作。

void Game()
{
	char board[ROW][COL];
	memset(board, ' ', sizeof(board));   //用空格去初始化
	char result = 'N';
	srand((unsigned long)time(NULL));  //使电脑随机落子
    while (1)
	{
		system("cls");   //实现清屏
		ComputerMove(board, ROW, COL);
		ShowBoard(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != 'N')
		{
			break;
		}
		PlayerMove(board, ROW, COL);
		ShowBoard(board, ROW, COL);
		result = Judge(board, ROW, COL);
		if (result != 'N')
		{
			break;
		}
	}
	switch (result)   //'X' 'O' 'E' 'N'作为switch语句的选择项
	{
	case 'X':
		printf("You Win! :)\n");
		break;
	case 'O':
		printf("You Lose, Computer Win! :(\n");
		break;
	case 'E':
		printf("平局,恭喜!\n");
		break;
	default:
		break;
	}
}

7、判断函数Judge:
游戏要想继续,每走一步就要显示一个结果。要非常清楚三子棋赢得条件是什么,要么连续三行或三列一样,要么对角线元素一样,并且不能等于空。这就是判断函数要实现的功能。

char Judge(char board[][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (; 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[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[1][1] != ' ') //判断反对角线
	{
		return board[1][1];
	}
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				return 'N'; //返回结果
			}
		}
	}
	return 'E'; //判断完,满了并且没成说明平局
}

8、主函数main():
负责将其他函数串起来,使得思路非常清晰switch语句分三种情况,1和2执行菜单,其他的数字说明输入错误。

int main()
{
	int select = 0;
	int quit = 0;
	while (!quit)
	{
		ShowUI();
		scanf("%d", &select);
		switch (select)
		{
		case 1:
			Game();
			break;
		case 2:
			quit = 1;
			printf("Bye,Bye!\n");
			break;
		default:
			printf("Please Enter Again!\n");
			break;
		}
	}
    system("pause");
	return 0;
}

运行结果示例:
棋盘界面
在这里棋盘界面插入图片描述
平局
在这里插入图片描述
你输了
在这里插入图片描述
你赢了
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值