Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /**
- * 截止:2017年05月27日 23:59:59
- * 分值:1.5分,酌情扣分
- * 难度:★★☆☆☆
- * 提交:私聊我提交答案
- * 需求:完成Board类的isEnd方法;本程序仅能在php-cli环境下运行,别问我cli和五子棋是什么;请合理运用类中提供的常量
- */
- /**
- * 五子棋程序
- * @author 肚肚
- */
- if (php_sapi_name() !== 'cli') {
- exit('请使用php-cli运行');
- }
- /**
- * 工具静态类
- */
- class Tool {
- private static $colors = [
- 'reset' => "\033[0m",
- 'bold' => "\033[1m",
- 'black' => "\033[30m",
- 'red' => "\033[31m",
- 'green' => "\033[32m",
- 'yellow' => "\033[33m",
- 'blue' => "\033[34m",
- 'magenta' => "\033[35m",
- 'cyan' => "\033[36m",
- 'white' => "\033[37m"
- ];
- public static function println ($msg, $params = [], $is_scan = FALSE, $color = FALSE) {
- $msg = vsprintf($msg, $params);
- if ($color && isset(self::$colors[$color]) && PHP_OS !== 'WINNT') {
- $msg = self::$colors[$color] . $msg . self::$colors['reset'];
- }
- if ($is_scan) {
- echo $msg;
- return PHP_OS === 'WINNT' ? stream_get_line(STDIN, 1024, PHP_EOL) : readline('');
- } else {
- echo $msg . PHP_EOL;
- }
- }
- }
- /**
- * 语言包工厂类
- */
- class Language {
- const CURRENT_BOARD = '目前棋盘:';
- const ENTER_DIMENSION = '请输入棋盘大小(范围为%d<=n<=%d,生成出的棋盘大小为n*n),或者输入q退出:';
- const ENTER_POSITION = '请输入您要下的位置(格式:行 列):';
- const INVALID_FORMAT = '非法格式!';
- const INVALID_DIMENSION = '大小不合法!';
- const INVALID_POSITION = '非法位置!';
- const MADE_MOVE = '%s的决定:%d %d';
- const WON = '%s赢了!';
- const DRAW = '平局!';
- const AI = 'AI';
- const YOU = '你';
- }
- /**
- * 棋盘类
- */
- class Board {
- private $board = []; // 棋盘
- private $n = 0; // 棋盘大小
- private $player = 0; // 目前玩家
- private $last_move = [null, null]; // 上一步
- const PLAYER_AI = 0; // AI编号
- const PLAYER_ME = 1; // 玩家编号
- const DIM_LOWER = 8; // 棋盘大小下限
- const DIM_UPPER = 15; // 棋盘大小上限
- const LABEL_EMPTY = '-'; // 格子空值
- const LABEL_AI = 'X'; // 格子被AI占领的值
- const LABEL_ME = 'O'; // 格子被玩家占领的值
- const DIR_VERTICAL = 0; // 纵向
- const DIR_HORIZONTAL = 1; // 横向
- const DIR_DIAGONALL = 2; // 左斜
- const DIR_DIAGONALR = 3; // 右斜
- const STATE_ONGOING = -1; // 游戏未结束
- const STATE_DRAW = -2; // 平局
- public function __construct ($n) {
- $this->board = array_fill(0, $n, array_fill(0, $n, Board::LABEL_EMPTY));
- $this->n = $n;
- $this->player = mt_rand(self::PLAYER_AI, self::PLAYER_ME);
- }
- /**
- * 显示棋盘
- */
- public function display () {
- echo Language::CURRENT_BOARD . PHP_EOL;
- echo ' ';
- for ($i = 0; $i < $this->n; ++$i) {
- printf(' %2d', $i);
- }
- echo PHP_EOL;
- for ($i = 0; $i < $this->n; ++$i) {
- printf('%2d', $i);
- for ($j = 0; $j < $this->n; ++$j) {
- printf(' %2s', $this->getCell($i, $j));
- }
- echo PHP_EOL;
- }
- }
- /**
- * 获取对应格子的值
- * @param int $row 行
- * @param int $row 列
- * @return string
- */
- private function getCell ($row, $col) {
- return $this->board[$row][$col];
- }
- /**
- * 检查游戏是否结束
- * @return mixed 如果游戏结束,则返回获胜玩家的编号,否则返回self::STATE_DRAW
- * 如果游戏没结束,则返回self::STATE_ONGOING
- */
- public function isEnd () {
- $row_ls = max($this->last_move[0] - 4, 0 );
- $col_ls = max($this->last_move[1] - 4, 0 );
- $row_rs = min($this->last_move[0] + 4, $this->n - 1);
- $col_rs = min($this->last_move[1] + 4, $this->n - 1);
- $label = $this->getCell($this->last_move[0], $this->last_move[1]);
- $options = [
- [$row_ls, $row_rs, $this->last_move[1]],
- [$col_ls, $col_rs, $this->last_move[0]],
- [$row_ls, $row_rs, 1 ],
- [$row_rs, $row_ls, -1 ]
- ];
- for ($dir = self::DIR_VERTICAL; $dir <= self::DIR_HORIZONTAL; ++$dir) {
- for ($start = $options[$dir][0], $idx2 = $options[$dir][2]; $options[$dir][1] - $start >= 4; ++$start) {
- $interrupted = FALSE;
- for ($idx = $start, $end = $idx + 4; $idx <= $end; ++$idx) {
- $val = $dir === self::DIR_VERTICAL ? $this->getCell($idx, $idx2) : $this->getCell($idx2, $idx);
- if ($val !== $label) {
- $interrupted = TRUE;
- break;
- }
- }
- if (!$interrupted) {
- return $this->player;
- }
- }
- }
- for ($dir = self::DIR_DIAGONALL; $dir <= self::DIR_DIAGONALR; ++$dir) {
- $start_col = $col_ls;
- $start_row = $options[$dir][0];
- for (; $this->last_move[1] - $start_col >= 4; ++$start_col, $start_row += $options[$dir][2]) {
- $interrupted = FALSE;
- $row = $start_row;
- $col = $start_col;
- $end_row = $row + 4;
- $end_col = $col + 4;
- for (; $row <= $end_row && $col <= $end_col; ++$col, $row += $options[$dir][2]) {
- if ($this->getCell($row, $col) !== $label) {
- $interrupted = TRUE;
- break;
- }
- }
- if (!$interrupted) {
- return $this->player;
- }
- }
- }
- $board_str = json_encode($this->board);
- return str_replace(self::LABEL_EMPTY, '', $board_str) === $board_str ? self::STATE_DRAW : self::STATE_ONGOING;
- }
- /**
- * 随机选择一个下棋的位置
- * @return array 包含了行、列的数组
- */
- public function pickMove () {
- do {
- $row = mt_rand(0, $this->n - 1);
- $col = mt_rand(0, $this->n - 1);
- } while (!$this->isValidMove($row, $col));
- return [$row, $col];
- }
- /**
- * 下棋
- * @param int $row 行
- * @param int $col 列
- */
- public function makeMove ($row, $col) {
- $this->board[$row][$col] = $this->player === self::PLAYER_AI ? self::LABEL_AI : self::LABEL_ME;
- $this->last_move = [$row, $col];
- Tool::println(Language::MADE_MOVE, [$this->player === self::PLAYER_AI ? Language::AI : Language::YOU, $row, $col], FALSE, 'blue');
- }
- /**
- * 检查步数是否合法
- * @param int $row 行
- * @param int $col 列
- * @return bool 是否合法
- */
- public function isValidMove ($row, $col) {
- return isset($this->board[$row][$col]) && $this->board[$row][$col] === self::LABEL_EMPTY;
- }
- /**
- * 切换玩家
- */
- public function toNextPlayer () {
- $this->player ^= 1;
- }
- /**
- * 获取目前玩家
- * @return int 玩家
- */
- public function getCurrentPlayer () {
- return $this->player;
- }
- }
- while (TRUE) {
- // 提示输入棋盘大小或者退出游戏
- $n = Tool::println(Language::ENTER_DIMENSION, [Board::DIM_LOWER, Board::DIM_UPPER], TRUE, 'green');
- if ($n === 'q') {
- break;
- }
- // 检查大小范围
- $n = intval($n);
- if ($n < Board::DIM_LOWER || $n > Board::DIM_UPPER) {
- Tool::println(Language::INVALID_DIMENSION, FALSE, 'red');
- continue;
- }
- $board = new Board($n);
- $board->display();
- while (TRUE) {
- $row = $col = 0;
- // 判断目前玩家并选择作出决定
- switch ($board->getCurrentPlayer()) {
- case Board::PLAYER_AI:
- list($row, $col) = $board->pickMove();
- break;
- case Board::PLAYER_ME:
- while (TRUE) {
- $params = explode(' ', Tool::println(Language::ENTER_POSITION, [], TRUE, 'green'));
- if (count($params) !== 2) {
- Tool::println(Language::INVALID_FORMAT, FALSE, 'red');
- continue;
- }
- list($row, $col) = array_map('intval', $params);
- if (!$board->isValidMove($row, $col)) {
- Tool::println(Language::INVALID_POSITION, FALSE, 'red');
- continue;
- }
- break;
- }
- break;
- }
- $board->makeMove($row, $col);
- $board->display();
- // 检查游戏是否结束
- if (($state = $board->isEnd()) !== Board::STATE_ONGOING) {
- switch ($state) {
- case Board::STATE_DRAW:
- Tool::println(Language::DRAW, [], FALSE, 'magenta');
- break;
- default:
- Tool::println(Language::WON, [$state == Board::PLAYER_AI ? Language::AI : Language::YOU], FALSE, 'magenta');
- break;
- }
- break;
- }
- // 移动到下个玩家
- $board->toNextPlayer();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment