Building a Tic-Tac-Toe Game on Solana: A Step-by-Step Guide Using Anchor and Rust

ajayiajayi
8 min read

Blockchain technology has revolutionized how we think about decentralized applications (dApps). Solana has emerged as a high-performance contender among the various blockchain platforms, offering fast transaction speeds and low costs.

To simplify the development process on Solana, the Anchor framework was created. In this article, we'll explore how Anchor and Solana work together, and build a decentralized Tic-Tac-Toe game on Solana using Rust programming language, and the Anchor framework.

For decentralized apps (dApps), Solana provides a fast, affordable environment, while Anchor makes creating smart contracts easier.

Accessing Free SOL: How to Use the Solana Faucet for Development

Solana uses the Solana Faucet to obtain free SOL (the native cryptocurrency of the Solana network) for testing and development purposes.

You can access the faucet for the Devnet at the following URL Devnet Faucet https://solfaucet.com/ You simply need to provide your Solana wallet address, and the faucet will send a small amount of SOL to that address.

Make sure you’re connected to the Devnet when requesting funds. For specific networks, you might also find faucet options like Testnet Faucet.

Available through various community tools or projects, but check the official documentation for details.

Always remember to use these funds only for development and testing on the respective networks!

Understanding Solana

Solana’s high throughput and low fees make it an ideal blockchain platform for building games and other dApps.

It uses a unique con/sensus mechanism called Proof of History (PoH) and Proof of Stake (PoS), allowing it to process thousands of transactions per second.

Some key features of Solana include:

  1. High speed and low latency

  2. Low transaction costs

  3. Smart contract functionality

  4. Support for decentralized applications (dApps).

Kindly visit the Solana documentation page to learn more about the Solana ecosystem.

Prerequisites on how to build on the Solana blockchain

  1. Basic Knowledge of Programming: Familiarity with JavaScript or Rust is helpful.

Node.js and npm: Make sure you have Node.js installed. You can download it from nodejs.org.

Step 1: Set Up Your Development Environment

  1. Install Rust:

    • Solana programs (smart contracts) are primarily written in Rust. Install Rust using the following command:

After installation, update your path by running:

Verify the installation:

Install Solana CLI:

  • The Solana Command Line (CLI) is essential for interacting with the Solana blockchain.

  • You can install the CLI with the following command:

Verify the installation for the Solana CLI:

Set Up Your Wallet:

  • Create a new wallet with the CLI

Set your wallet as the default:

Configure the CLI:

  • Set your network to the Devnet for testing

Step 2: Create Your First Solana Program

  1. Create a New Directory:

    • Create a new directory for your project and navigate to it:

Initialize a New Rust Project:

  • Use Cargo (Rust’s package manager) to create a new library:

Update Cargo.toml:

  • Open the Cargo.toml file and add the following dependencies:

Write Your Program:

  • Open src/lib.rs and replace its content with a simple program. Here’s an example that logs a message:

Step 3: Build and Deploy Your Program

  1. Build Your Program:

    • Run the following command to build your program:

  • This compiles your Rust code to a BPF (Berkeley Packet Filter) binary that can run on Solana.

Deploy to Devnet:

  • Use the following command to deploy your program:

  • Note the program ID returned after deployment; you’ll need it for interactions.

Step 4: Interact with Your Program

  1. Write a Client Application from your terminal:

    • Create a new directory for your client:

Create a JavaScript File:

Create a file called index.js and add the following code to interact with your deployed program:

Run Your Client:

  • Replace your secret key array and your_program_id_here with the appropriate values.

  • Run your client script

With the environment set up, we have successfully created a simple Solana program, we have deployed it, and we also interacted with it using a client application. Kindly check out the Solana documentation for more advanced topics and best practices.

Why Anchor?

Anchor is a framework designed for Solana’s Sealevel runtime, that streamlines the process of creating programs by providing an easy-to-use development structure and abstracting complex parts of smart contract development.

It’s the perfect combination for developers who want to write efficient programs without dealing with low-level complexities.

It aims to solve common pain points in Solana development by:

  1. Reducing boilerplate code

  2. Providing a more intuitive programming model

  3. Offering better error handling

  4. Simplifying account management

After setting up our environment for the Solana CLI, it gives us the basis to install the anchor framework easily.

Below are processes for going about with the anchor framework

Install Anchor:

  • Install Anchor by running:

Verify the installation:

Set Up Your Wallet:

  • Create a new wallet:

Set your wallet as the default:

Configure the CLI:

  • Set your network to the Devnet:

Step 2: Create Your First Anchor Program

  1. Initialize a New Anchor Project:

    • Create a new Anchor project

Explore the Project Structure:

  • Your project will have the following key directories:

    • programs/: Contains your smart contracts.

    • tests/: Contains tests for your program.

    • Anchor.toml: Configuration file for your Anchor project.

Write Your Program:

  • Open programs/my_anchor_project/src/lib.rs and replace the content with a simple program:

Step 3: Build and Deploy Your Program

  1. Build Your Program:

    • Build the Anchor program by running anchor build:

Deploy to Devnet:

  • Deploy your program to devnet:

Note the program ID returned after deployment; you’ll need it for interaction.

Step 4: Interact with Your Program

  1. Write a Client Application:

    • Inside your project, create a new directory for the client:

Create a JavaScript File:

  • Create a file called index.js and add the following code to interact with your deployed program:

Set Up the IDL:

  • Generate the IDL (Interface Definition Language) file

Load the IDL in your index.js:

Run Your Client:

  • Replace your secret key array and YOUR_PROGRAM_ID with the appropriate values.

  • Run your client script

With the environment set up, we have successfully created a simple program using anchor, we have deployed it, and we also interacted with it using a client application. Kindly check out the Anchor documentation for more advanced topics and best practices.

Rust Programming Language: The Language of Choice

Rust is the primary programming language for developing Solana and Anchor. It offers several advantages:

  1. Memory safety without garbage collection

  2. Concurrency without data races

  3. Abstraction without overhead

  4. Strong type system and ownership model

These features make Rust an excellent choice for blockchain development, where security and performance are crucial. To write more efficient code on Rust, kindly visit the Rust Documentation page

Prerequisites

Before diving into the project, you’ll need:

  1. A basic understanding of Rust programming.

  2. Installed Rust, Solana CLI, and Anchor on your machine.

  3. Familiarity with blockchain basics and Solana programs (smart contracts).

The project setup

After following the above procedures, the next step is to initialize the next project.

This command creates the basic folder structure for your project, including key files for smart contract logic, tests, and configurations.

Code Breakdown

The game logic for Tic-Tac-Toe is defined in the following Rust code using the Anchor framework. Let’s walk through the key components of this code step by step.

Imports and Setup

anchor_lang::prelude::*: Imports common types and macros used in Solana programs.

num_derive::* and num_traits::*: Provides functionalities for working with numeric types and conversions.

declare_id!: Declares the program ID, a unique identifier for this Solana program.

The Program Module

#[program]: Declares the main program module.

Functions:

setup_game: Initializes the game with two players.

player_two: Public key of the second player.

The function calls start on the game account to set up the players.

play: Handles making a move (i.e., placing a mark on the board).

Check if the player making the move is the correct player.

Calls the play method of the game account to place a tile.

The Game Structure

Methods:

start: Initializes the game by setting the players and marking the game as started (turn set to 1).

is_active: Checks if the game is still ongoing.

current_player_index: Determines whose turn it is based on the turn counter.

current_player: Returns the public key of the player whose turn it is.

play: Place the player's mark on the board. It first checks if the game is active, then validates if the tile is free.

Checking Game State

update_state: Checks whether a player has won or if the game is tied.

is_winning_trio: This helper function checks for a winning combination in rows, columns, or diagonals

Game Account and Structs

Game Struct:

Stores the two players' public keys.

The turn keeps track of whose turn it is.

The board holds the current state of the game (empty or filled).

state: Holds the game state (active, tie, or won).

Enums for Game State and Player Sign

GameState: Enum to track whether the game is active, tied, or has been won.

Sign: Enum for player marks (either X or O).

Error Handling

TicTacToeError: Custom error enum for handling common game errors like out-of-bounds moves or invalid turns

Account Contexts

SetupGame: Handles initializing the game account and linking it with player one.

Play: The context for the play function, holding the game and player accounts.

This is only the game implementation code using the anchor framework on Solana using Rust. The full code can be found in my GitHub repository where u will also find the tests associated with this game in the test folder.

Conclusion

This implementation of the Tic-Tac-Toe game demonstrates how to use the Anchor framework to create a basic game on the Solana blockchain.

Using Solana's blockchain architecture, the application controls player turns, verifies winning conditions, and guarantees proper game mechanics.

A large portion of the complexity is abstracted by the Anchor framework, which facilitates game logic concentration.

10
Subscribe to my newsletter

Read articles from ajayi directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ajayi
ajayi

I, Ajayi Damola Ramon am a passionate and detail-oriented professional with a strong foundation in Statistics and expertise in Rust development. As a Blockchain Developer, I specialize in leveraging Rust to build decentralized applications and smart contracts, particularly in the ICP ecosystem. My technical journey combines deep analytical skills as a Data Analyst with hands-on coding experience, allowing me to solve complex problems through data-driven insights and efficient Rust solutions. With a background in statistics, I excel at breaking down technical concepts and translating them into actionable insights, both in the world of data science and blockchain development. I am constantly exploring new innovations in the tech world, especially Rust, Go, and blockchain technologies, and I am committed to contributing to the open-source community through projects and technical writing. Beyond coding, I am passionate about sharing knowledge through technical articles and tutorials. I regularly publish in-depth guides on Rust, blockchain, and data analytics on my Hashnode blog, helping developers of all levels deepen their understanding of emerging technologies. Connect with me to collaborate on cutting-edge blockchain projects or to explore the fascinating intersection of data, statistics, and decentralized systems.