【C++】五子棋 简单实现

游戏效果预览

五子棋游戏界面

功能模块

  •   界面显示

  •   游戏逻辑

    •   判断输赢
    •   游戏流程控制
  •   玩家行动

  •   电脑随机行动

源代码展示

  • 界面展示类
#pragma once

#include <stdio.h>
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
#include <Windows.h>

#define ROW 10
#define COL 10
typedef unsigned int _ui;

typedef struct Pos				//玩家位置结构体
{
	int x;
	int y;
}Pos;

class Show						//界面展示 类
{
public:
	void ShowBlack(std::vector<std::vector<char> >& _arr)
	{
		_ui row = _arr.size();
		_ui col = _arr[0].size();
		std::cout << "\n\t 玩家1:o \t 玩家2:x" << std::endl;
		std::cout << "\n 0   1   2   3   4   5   6   7   8   9   10" << std::endl;
		for (_ui i = 0; i < row; ++i)
		{
			std::cout << "   ";
			for (_ui j = 0; j < col; ++j)
			{
				std::cout << "|---";
			}
			std::cout << "|" << std::endl;
			printf("%2d ", i + 1);
			for (_ui j = 0; j < col; ++j)
			{
				std::cout << "| ";
				switch (_arr[i][j])
				{
				case '1': std::cout << "o";
					break; 
				case '2': std::cout << "x";
					break;
				case ' ': 
				default : std::cout << " ";
					break;
				}
				std::cout << " ";
			}
			std::cout << "|" << std::endl;
		}
		std::cout << "   +---+---+---+---+---+---+---+---+---+---+" << std::endl;
	}
};
  • 玩家行为类
class Player			//玩家 类
{
protected:
	std::string _name;	//昵称
	double WinRate;		//胜率
	_ui win_count;		//胜场
	_ui lose_count;		//败场
	char chess;			//玩家棋子

public:

	Player()
		:_name("Player")
		, WinRate(0.0)
		, win_count(0)
		, lose_count(0)
		, chess( ' ' )
	{}

	//获取昵称
	std::string& GetName()
	{
		return _name;
	}

	//设置棋子颜色
	void SetChess(char mod)
	{
		chess = mod;
	}

	//获得棋子颜色
	char GetChess()
	{
		return chess;
	}

	//输入昵称
	void input_name(std::string name)
	{
		swap(_name, name);
	}

	//增加胜场
	void AddWin()
	{
		++win_count;
		CalcWinRate();
	}

	//增加败场
	void AddLose()
	{
		++lose_count;
		CalcWinRate();
	}

	//玩家行动
	virtual Pos Action(std::vector<std::vector<char> >& _arr)
	{
		char c;	//用于接收玩家输入坐标中的‘,’
		Pos pos;
		while (1)
		{
			std::cout << "[玩家 " << _name << "]:";
			std::cout << "请落子(x,y):";
			std::cin >> pos.x >> c >> pos.y;
			pos.x -= 1, pos.y -= 1;
			//落子出范围
			if (pos.x >= ROW || pos.x < 0 || pos.y >= COL || pos.y < 0)
				std::cout << "您落子的位置不在服务区,请重新落子" << std::endl;
			else if (_arr[pos.x][pos.y] != ' ')					//落子位置有子
				std::cout << "您落子的位置已被人抢占先机,请重新抉择吧!" << std::endl;
			else
				break;
		}
		_arr[pos.x][pos.y] = chess;
		return pos;
	}

	void SetName()
	{
		//写入玩家昵称
		std::cout << "敢问英雄大名?:";
		std::cin >> _name;
	}

private:

	//计算胜率
	void CalcWinRate()
	{
		WinRate = win_count * 1.0 / lose_count;
	}
};



class Computer : public Player		//电脑 类
{
public:

	//电脑行动
	virtual Pos Action(std::vector<std::vector<char> >& _arr)
	{
		srand((unsigned)time(NULL));
		Pos pos;

		do
		{
			pos.x = rand() % ROW;
			pos.y = rand() % COL;
		} while (_arr[pos.x][pos.y] != ' ');

		_arr[pos.x][pos.y] = chess;

		return pos;
	}
};
  • 游戏逻辑类(采用单例模式,线程不安全)
class Game									//游戏流程
{
protected:
	Game()									//单例:初始化游戏
	{
		//清空棋盘
		for (int i = 0; i < ROW; ++i)
		{
			std::vector<char> col_con;
			col_con.assign(COL, ' ');
			_arr.push_back(col_con);
		}
	}
private:
	static Game* _game;							//单例
	std::vector<std::vector<char> > _arr;	//棋盘
	Show _show;								//UI
	Player *_player[2];						//玩家1,玩家2,电脑

public:

	static Game* instance()			//单例:创建类
	{
		if (_game == NULL)
			_game = new Game();
		return _game;
	}

	//判断输赢,平局返回0,未结束返回-1,否则返回棋子颜色。
	int IsWin(Pos& pos)
	{
		char chess = _arr[pos.x][pos.y];
		if (' ' == chess)
			return -1;

		if ((BlockOfCount(pos, -1, 1, chess) + BlockOfCount(pos, 1, -1, chess) + 1 == 5) ||
			(BlockOfCount(pos,  0, 1, chess) + BlockOfCount(pos, 0, -1, chess) + 1 == 5) ||
			(BlockOfCount(pos, 1, 1, chess) + BlockOfCount(pos, -1, -1, chess) + 1 == 5) ||
			(BlockOfCount(pos,  1, 0, chess) + BlockOfCount(pos, -1, 0, chess) + 1 == 5))
			return chess;
		return CheckFullChess();
	}

	//游戏流程控制
	void RunGame()
	{
		Pos pos = { 0 };			//下次行动位置
		int ret = 0;				//游戏结果
		int round = 1;				//游戏轮次

		int mod = SetMod();			//设置游戏相关选项
		system("cls");
		_show.ShowBlack(_arr);		//打印棋盘

		for (; (ret = IsWin(pos)) < 0; mod = (mod + 1) % 2)
		{
			pos = _player[mod]->Action(_arr);
			system("cls");
			_show.ShowBlack(_arr);
		} 

		if (ret != 0)
		{
			std::cout << "玩家:" << "[" << _player[(mod + 1) % 2]->GetName() << "] 胜!" << std::endl;
			_player[(mod + 1) % 2]->AddWin();
			_player[mod]->AddLose();
		}
		else
			std::cout << "平局!" << std::endl;
		system("pause");
	}

	//设置游戏相关选项
	int SetMod()
	{
		int mod = ChooseGameMod();

		std::cout << "玩家1:";
		_player[0] = new Player;
		_player[0]->SetName();

		if (mod)		                //双人模式
		{
			std::cout << "玩家2:";
			_player[1] = new Player;
			_player[1]->SetName();
		}
		else							//单人模式
			_player[1] = new Computer;

		//选择先行玩家
		mod = ChoosePlayerAction(mod);	//这里 mod 表示先行玩家

		//为先行玩家分配棋子颜色
		_player[mod]->SetChess('1'),
		_player[(mod + 1) % 2]->SetChess('2');

		return mod;
	}

private:
	//判断有多少连子
	int BlockOfCount(Pos pos, int off_x, int off_y, char chess)
	{
		pos.x += off_x;
		pos.y += off_y;

		if (pos.x >= ROW || pos.x < 0 || pos.y >= ROW || pos.y < 0)
			return 0;

		if (_arr[pos.x][pos.y] == chess)
			return 1 + BlockOfCount(pos, off_x, off_y, chess);
		return 0;
	}

	int ChooseGameMod()
	{
		int ret;
		std::cout << "请选择游戏模式:" << std::endl;
		std::cout << "0.单人模式  1.双人模式" << std::endl;
		std::cin >> ret;
		return ret;
	}

	int ChoosePlayerAction(int mod)
	{
		int ret;
		std::cout << "请选择先行玩家:" << std::endl;
		if (mod)
			std::cout << "0.玩家1  1.玩家2" << std::endl;
		else
			std::cout << "0.玩家   1.电脑" << std::endl;
		std::cin >> ret;
		return ret;
	}

	//判断棋盘是否装满
	int CheckFullChess()
	{
		for (int i = 0; i < ROW; ++i)
		{
			for (int j = 0; j < COL; ++j)
			{
				if (_arr[i][j] == ' ')
					return -1;
			}
		}
		return 0;
	}
};
  • 主函数(main)
#include "wuzi.hpp"

extern class Game;
Game* Game::_game = NULL;

void PlayGame()
{
	Game *game = Game::instance();
	game->RunGame();
}

int main()
{
	PlayGame();
	return 0;
}

未实现功能

  • 图形界面
  • 悔棋
  • 网络联机

猜你喜欢

转载自blog.csdn.net/qq_41866437/article/details/83958882
今日推荐