Go 言語で「基礎プログラミング演習 I 〜100 本ノック上級編」を解いてみる-No.85「石取りゲーム」

はじめに

「基礎プログラミング演習 I 〜100 本ノック上級編」を解いてみます。

取り扱う問題は以下のサイトを引用させていただきました。

検証環境

1
2
3
4
5
6
7
8
9
$ uname -moi
x86_64 unknown GNU/Linux

$ head -n 2 /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"

$ go version | head -n 1
go version go1.16.3 linux/amd64

問題

No. 85 石取りゲーム

最初に石の個数を入力し(10 個以上とする)、二人のプレイヤーが交互に 1〜3 個ずつ石を取り、最後の 1 個を取った方が負けとなるゲームがある。このゲームプログラムを作成せよ。具体的には実行例を参照のこと。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 【実行例、下線部は入力例】
$ ./knock85
石の数を入力してください(10以上): 15
石の数: 15
プレイヤー1の番です
何個取る(1〜3個)? 3
石の数: 12
プレイヤー2の番です
何個取る(1〜3個)? 2
石の数: 10
プレイヤー1の番です
何個取る(1〜3個)? 4
プレイヤー1の番です
何個取る(1〜3個)? 3
石の数: 7
プレイヤー2の番です
何個取る(1〜3個)? 3
石の数: 4
プレイヤー1の番です
何個取る(1〜3個)? 2
石の数: 2
プレイヤー2の番です
何個取る(1〜3個)? 1
石の数: 1
プレイヤー2の勝ち
$ ./knock85
石の数を入力してください(10以上): 10
石の数: 10
プレイヤー1の番です
何個取る(1〜3個)? 3
石の数: 7
プレイヤー2の番です
何個取る(1〜3個)? 2
石の数: 5
プレイヤー1の番です
何個取る(1〜3個)? 3
石の数: 2
プレイヤー2の番です
何個取る(1〜3個)? 3
石の数: -1
プレイヤー2の反則負け

回答

knock85.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package main

import (
	"fmt"
)

func main() {
	const countOfPlayers = 2

	stones := 0
	for stones < 10 {
		fmt.Print("石の数を入力してください。(10以上) : ")
		fmt.Scan(&stones)
	}

	fmt.Printf("石の数: %d\n", stones)

	for playerNo := 1; ; playerNo = playerNo%countOfPlayers + 1 {
		takedStones := 0
		for !(1 <= takedStones && takedStones <= 3) {
			fmt.Printf("プレイヤー%dの番です\n", (playerNo))
			fmt.Print("何個取る(1〜3個) ? ")
			fmt.Scan(&takedStones)
		}

		stones -= takedStones
		fmt.Printf("石の数: %d\n", stones)

		switch stones {
		case -1:
			fmt.Printf("プレイヤー%dの反則負け\n", (playerNo))
		case 0:
			fmt.Printf("プレイヤー%dの負け\n", (playerNo))
		case 1:
			fmt.Printf("プレイヤー%dの勝ち\n", (playerNo))
		}

		if stones <= 1 {
			break
		}
	}
}

実行

1
$ go run knock85.go

ひとこと

プレイヤーが間違って全部とってしまったケースの出力例が無いため、仕様を想像し実装しました。