C语言实现简单经典小游戏三子棋

前言:基于c的三子棋的实现,

平台:vs2022

目录

1.算法思路

2.代码模块

2.1.gittee源码

3.文案金句


1.算法思路

       将棋盘看作二维数组,但是在打印时要打印出边界,在选手下棋和电脑下棋前,判断棋盘是否还有位置,电脑下棋在此处实现的是两种方式,随机下棋和根据情况下棋,所谓随机下棋,就是根据生成的合法随机数来确定下棋的位置,而对于第二种,我的设计就是尽量让电脑模拟我们人的思维,在判断下棋时要做出对自己最优的决策,自己赢>堵对手>随机下棋,逻辑实现也很简单,详见代码。

2.代码模块

//game.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <windows.h>
#define ROW 3
#define COL 3
static int Count = 0;
//初始化棋盘
void init(char board[ROW][COL], int row, int col);
//打印棋盘
void display(char board[ROW][COL], int row, int col);
//玩家下棋
void playermove(char board[ROW][COL], int row, int col);
//电脑下棋
void computermove(char board[ROW][COL], int row, int col);
//AI电脑下棋
void aicomputermove(char board[ROW][COL], int row, int col);
//判断输赢
char iswin(char board[ROW][COL], int row, int col);
//判断棋盘是否已满
int isfull(char board[ROW][COL], int row, int col);
//game.cpp
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"


//初始化棋盘
void init(char board[ROW][COL], int row, int col)
{
	memset(board, ' ', row*col*sizeof(char));//还是注意在数组定义外面尽量避免用sizeof算大小,会出错

}
//打印棋盘
void display(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		int j = 0;
		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 playermove(char board[ROW][COL], int row, int col)
{
	int x, y;
	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 computermove(char board[ROW][COL], int row, int col)
{
	printf("电脑下棋:->\n");
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}

}
//AI电脑下棋
void aicomputermove(char board[ROW][COL], int row, int col)
{
	//判断当前棋盘后选择最优算法,以下的几种情况只能选择一种,所以都有限制条件count=0(电脑还没走)时
	printf("电脑下棋\n");
	//判断是否自己还差一步就赢了,则优先选择该步
	int count = 0;//表示电脑走的步数
		  //判断自己一行是否有了两个
	if(!count)
	for (int i = 0; i < row; i++)
	{
		if (board[i][0] == '#' && board[i][1] == '#' && board[i][2] == ' ')
		{
			board[i][2] = '#';
			count++;
			break;
		}
		else if (board[i][0] == '#' && board[i][2] == '#' && board[i][1] == ' ')
		{
			board[i][1] = '#';
			count++;
			break;
		}
		else if (board[i][1] == '#' && board[i][2] == '#' && board[i][0] == ' ')
		{
			board[i][0] = '#';
			count++;
			break;
		}
	}
	//同理再判断列是否已经有了两个
	if (!count)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[0][j] == '#' && board[1][j] == '#' && board[2][j] == ' ')
			{
				board[2][j] = '#';
				count++;
				break;
			}
			else if (board[0][j] == '#' && board[2][j] == '#' && board[1][j] == ' ')
			{
				board[1][j] = '#';
				count++;
				break;
			}
			else if (board[1][j] == '#' && board[2][j] == '#' && board[0][j] == ' ')
			{
				board[0][j] = '#';
				count++;
				break;
			}
		}
	}
	//最后判断斜行
	if (!count)
	{

		if (board[0][0] == '#' && board[1][1] == '#' && board[2][2] == ' ')
		{
			board[2][2] = '#';
			count++;
		}
		else if (board[0][0] == '#' && board[2][2] == '#' && board[1][1] == ' ')
		{
			board[1][1] = '#';
			count++;
		}
		else if (board[1][1] == '#' && board[2][2] == '#' && board[0][0] == ' ')
		{
			board[0][0] = '#';
			count++;
		}
	}
	if (!count)
	{
		if (board[0][2] == '#' && board[1][1] == '#' && board[2][0] == ' ')
		{
			board[2][0] = '#';
			count++;
		}
		else if (board[0][2] == '#' && board[2][0] == '#' && board[1][1] == ' ')
		{
			board[1][1] = '#';
			count++;
		}
		else if (board[1][1] == '#' && board[2][0] == '#' && board[0][2] == ' ')
		{
			board[0][2] = '#';
			count++;
		}
	}
	//若以上都没有,那么就优先选择堵对方,先判断对方是否已经存在两个
	//判断对方的行
	if (!count)
	{
		for (int i = 0; i < row; i++)
		{
			if (board[i][0] == '*' && board[i][1] == '*' && board[i][2] == ' ')
			{
				board[i][2] = '#';
				count++;
				break;
			}
			else if (board[i][0] == '*' && board[i][2] == '*' && board[i][1] == ' ')
			{
				board[i][1] = '#';
				count++;
				break;
			}
			else if (board[i][1] == '*' && board[i][2] == '*' && board[i][0] == ' ')
			{
				board[i][0] = '#';
				count++;
				break;
			}
		}

	}
	//判断对方的列
	if (!count)
	{
		for (int j = 0; j < col; j++)
		{
			if (board[0][j] == '*' && board[1][j] == '*' && board[2][j] == ' ')
			{
				board[2][j] = '#';
				count++;
				break;
			}
			else if (board[0][j] == '*' && board[2][j] == '*' && board[1][j] == ' ')
			{
				board[1][j] = '#';
				count++;
				break;
			}
			else if (board[1][j] == '*' && board[2][j] == '*' && board[0][j] == ' ')
			{
				board[0][j] = '#';
				count++;
				break;
			}
		}
	}
	//判断对方的斜行
	if (!count)
	{

		if (board[0][0] == '*' && board[1][1] == '*' && board[2][2] == ' ')
		{
			board[2][2] = '#';
			count++;
		}
		else if (board[0][0] == '*' && board[2][2] == '*' && board[1][1] == ' ')
		{
			board[1][1] = '#';
			count++;
		}
		else if (board[1][1] == '*' && board[2][2] == '*' && board[0][0] == ' ')
		{
			board[0][0] = '#';
			count++;
		}
	}
	if (!count)
	{
		if (board[0][2] == '*' && board[1][1] == '*' && board[2][0] == ' ')
		{
			board[2][0] = '#';
			count++;
		}
		else if (board[0][2] == '*' && board[2][0] == '*' && board[1][1] == ' ')
		{
			board[1][1] = '#';
			count++;
		}
		else if (board[1][1] == '*' && board[2][0] == '*' && board[0][2] == ' ')
		{
			board[0][2] = '#';
			count++;
		}
	}
	//最后如果都没有,那么就可以随便走
	if (!count)
	{
		while (1)
		{
			int x = rand() % row;
			int y = rand() % col;
			if (board[x][y] == ' ')
			{
				board[x][y] = '#';
				break;
			}
		}
	}


 }
//判断输赢

char iswin(char board[ROW][COL], int row, int col)
{
	 //判断是否为一行,返回赢的人的字符
	for (int 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 (int j = 0; j < col; j++)
		if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
			return board[1][j];
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] && board[1][1] != ' ')
		return board[1][1];
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] && board[1][1] != ' ')
		return board[1][1];
	//如果没有返回则接下来判断平局(棋盘已满)
	if (isfull(board, row, col))//棋盘已满返回字符'Q'
	{
		return 'Q';
	}
	//如果以上都不满足,则表示可以继续,返回字符'C'
	return 'C';
}
//判断平局(棋盘已满)
int isfull(char board[ROW][COL], int row, int col)
{
	int flag = 1;
	for(int i=0;i<row;i++)
		for (int j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
			{
				flag = 0;
				break;
			}
		}
	return flag;
}
//test.cpp
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
    printf("********************************\n");
    printf("******     1.   play      ******\n");
    printf("******     0.   exit      ******\n");
    printf("注意:第三局开始加大游戏难度\n");
    printf("********************************\n");
}
void game()
{
    char board[ROW][COL]={0};
    //初始化棋盘
    init(board, ROW, COL);
    display(board, ROW, COL);
    char ch = 0;//判断游戏是否结束(包括输赢和平局)
    while (1)
    {
        //游戏进行步骤
        //玩家下棋
        if(Count>1)
             printf("难度升级,AI功能提升\n");
        playermove(board,ROW,COL);
        //打印棋盘
        display(board, ROW, COL);
        //判断输赢
        ch = iswin(board, ROW, COL);
        //printf("%c\n", ch);调试用
        if (ch != 'C')
        {
            ++Count;
            //printf("%d\n", Count);
            break;
        }
        //电脑下棋
        if (Count<= 1)
            computermove(board, ROW, COL);
        else
        {
            //难度升级
            aicomputermove(board, ROW, COL);
        }
        //打印棋盘
        display(board, ROW, COL);
        //判断输赢
        ch = iswin(board, ROW, COL);
        if (ch != 'C')
        {
            ++Count;
            //printf("%d\n", Count);
            break;
        }
    }
    //出来之后判断结果
    //printf("%c\n", ch);调试用
    if (ch == '*')
        printf("玩家赢\n");
    else if (ch == '#')
        printf("电脑赢\n");
    else if(ch=='Q')
        printf("平局\n");

}
int main()
{
    int input=0;
    srand((unsigned int)time(NULL));
    printf("请进入童年回忆小游戏之--井字棋\n");

    do {
        system("cls");
        menu();
        printf("请选择->");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            Sleep(2000);
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("数据输入有误,请重新输入\n");
            break;
        }

    } while (input);


    return 0;
}

2.1.gittee源码

详情见:https://gitee.com/lipersonalspaceaddress/practical-projects/tree/master/Project7/Project7

   

3.文案金句

     “ 一个人也可以很勇敢,很多时候我们都是一个人挺过来的不是吗?”

 希望这篇博客能让你学到东西的同时,更多的可以给你带来快乐...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值