C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++で解く「石を1個ずつ取り除くニムゲーム」の勝者予測プログラム

この問題はニムゲーム(Nim Game)と呼ばれるもので、山積みの石の数を表す正整数 N が与えられ、2人のプレイヤー playerAplayerB が交互に石を取っていくゲームです。私たちの課題は、このゲームの勝者を予測するプログラムを作成することです。

ニムゲームとは

ここでは、1つの山に積まれた石と、playerAplayerB の2人のプレイヤーがいます。各プレイヤーの番には、山から石をちょうど1個だけ取り除くことができます。playerA が先手として最初の石を取ることから始まり、最後に石を取ったプレイヤーが勝者となります。

具体的な例を見てみましょう。

入力:N = 6
出力:playerB
説明:
石の総数 = 6、石が取られる順序は
playerA → playerB → playerA → playerB → playerA → playerB

この場合、6個目の石は playerB が取るため、勝者は playerB になります。

解法アプローチ

この問題を解く一つの方法は、N の値と勝者の関係から一般的な規則性(公式)を見つけ出すことです。いくつかの N の値に対する勝者を確認してみましょう。

  • N = 1 のとき、勝者は playerA
  • N = 2 のとき、勝者は playerB
  • N = 3 のとき、勝者は playerA

これらの結果から、次のような規則が導き出せます。

  • N が奇数の場合: 勝者は playerA(先手)
  • N が偶数の場合: 勝者は playerB(後手)

これは直感的にも理解できます。各ターンで必ず1個の石が減っていくため、N が奇数なら最後の1個は先手の playerA が取り、偶数なら後手の playerB が取ることになるからです。したがって、N を2で割った余りを判定するだけで勝者を求められます。

C++での実装例

上記の解法を実装したプログラムが以下です。

#include<iostream>
using namespace std;

bool findGameofNimWinner(int N){
    if(N % 2 == 0)
        return 0;   // 偶数なら playerB の勝ち
    else
        return 1;   // 奇数なら playerA の勝ち
}
int main(){
    int N = 26;
    cout << "The winner of the Game of Nim is ";
    findGameofNimWinner(N) ? (cout << "Player A") : (cout << "Player B");
    return 0;
}

実行結果

The winner of the Game of Nim is Player B

N = 26 は偶数であるため、出力は Player B となり、規則通りに正しく判定できていることがわかります。

まとめ

この問題は、各ターンで石を1個しか取れないという制約があるため、N の偶奇を判定するだけで O(1) の計算量で勝者を特定できる非常にシンプルなゲーム理論の問題です。より一般的なニムゲーム(複数の山や複数個の石を取れるバリエーション)では XOR を使った戦略が必要になりますが、本問題のように単純なルールの場合は偶奇の判定だけで十分です。

  1. C++で配列要素の削除コストを最小限に抑えるアルゴリズム

    問題の概要 N個の要素を持つ配列が与えられます。この配列から、以下のルールに従って要素を削除していきます。 操作の内容は次のとおりです。まず配列から任意の2つの数を選び、そのうち大きい方を削除します。このとき発生するコストは、小さい方の数と等しくなります。この操作を繰り返し、一度に1つの要素だけを削除しながら、全体のコストを最小化することが目標です。 例として、配列 {4, 2, 5} を考えてみましょう。まず 4 と 2 を選び、コスト 2 を支払って 4 を削除します。続いて残った 5 を、再びコスト 2 で削除します。 解法のアプローチ この問題の解き方は非常にシンプルです。操作のコスト

  2. 【C++入門】通常の配列を任意のデフォルト値で初期化する方法

    配列全体を0で初期化する最も簡単な方法C++では、配列全体を0で初期化するのは非常に簡単です。宣言時に以下のように {0} を指定するだけで、すべての要素が0になります。int arr[10] = {0};0以外の値ではうまくいかない理由しかし、同じ方法で配列全体を0以外の値で初期化することはできません。次のようなコードを書いても、意図した結果にはなりません。int arr[10] = {5};この場合、最初の要素だけが5で初期化され、残りの9個の要素はすべて0で初期化されます。これは、初期化リストで明示的に値を指定しなかった要素には自動的に0が代入されるというC++の仕様によるものです。fo