0

I have a game called Ninja Gold that I have already coded successfully. I am using PHP with CodeIgniter. How it works is when the index page loads the session variables (Gold and Activities) are set if there are not any. By clicking each location, gold within a certain amount range is added to the total amount. The exception is the casino location where money could possibly be lost as well. This is created using the an odds generator to determine if the amount from the casino is won or lost. Once the location is clicked and the gold is added or lost, an activity message is displayed to tell the user what happened. Here is the code in my Ninjas controller:

defined('BASEPATH') OR exit('No direct script access allowed');
date_default_timezone_set('America/Los_Angeles');

class Ninjas extends CI_Controller {

    public function index()
    {
        if (!$this->session->userdata('gold') && !$this->session->userdata('activities'))
        {
            $this->session->set_userdata('gold', 0);
            $this->session->set_userdata('activities', [" ", "win"]);
        }
        $this->load->view('index');
    }

    public function process_money()
    {
        $building = $this->input->post('building');

        //for an alternative to if/else, going to use case/switch
        switch ($building) {
            case 'farm':
                $gold = rand(10,20);
                break;

            case 'cave':
                $gold = rand(5,10);
                break;

            case 'house':
                $gold = rand(2,5);
                break;

            case 'casino':
                $odds = rand(0,1);
                $gold = rand(0,50);
                if ($odds == 0)
                {
                    $gold *= -1;
                }
                break;

            default:
                $gold = 0;
                break;
        }

        if ($gold < 0)
        {
            $activity = ['You entered a casino and lost ' . $gold . ' gold(s). Ouch!', 'loss'];
        }
        else
        {
            $activity = ['You entered a ' . $building . ' and earned ' . $gold . ' gold(s)', 'win'];
        }
        // $activities = $this->session->userdata('activities');
        // array_unshift($activities, $activity);
        $this->session->set_userdata('activities', $activity);

        $running_total = $this->session->userdata('gold');
        $running_total += $gold;
        $this->session->set_userdata('gold', $running_total);

        redirect('http://localhost:8888/');
    }
}

Here is the index page code:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Ninja Gold</title>
        <link rel="stylesheet" href="<?= base_url('assets/css/style.css'); ?>">
    </head>
    <body>
        <h1>Your Gold: <?= $this->session->userdata('gold') ?></h1>
        <form action="/process_money" method="post">
            <h2>Farm</h2>
            <p>Earns 10-20 golds</p>
            <input type="hidden" name="building" value="farm">
            <input type="submit" value="Find Gold!">
        </form>
        <form action="/process_money" method="post">
            <h2>Cave</h2>
            <p>Earns 5-10 golds</p>
            <input type="hidden" name="building" value="cave">
            <input type="submit" value="Find Gold!">
        </form>
        <form action="/process_money" method="post">
            <h2>House</h2>
            <p>Earns 2-5 golds</p>
            <input type="hidden" name="building" value="house">
            <input type="submit" value="Find Gold!">
        </form>
        <form action="/process_money" method="post">
            <h2>Casino</h2>
            <p>Earns/Loses 0-50 golds</p>
            <input type="hidden" name="building" value="casino">
            <input type="submit" value="Find Gold!">
        </form>
        <div class="activities">
<?php foreach ($this->session->userdata('activities') as $activity) { ?>
            <p class="<?= $activity[1] ?>"><?= $activity[0] ?></p>
<?php } ?>
        </div>
    </body>
</html>

I am using forms to submit the data with POST methods. What I want to do is recode the game to only have the index function in the Ninjas controller and not submit to another URL (ninjas/process_money) when the locations forms (name = "building" in code) are submitted. That way I can have music play in the background and not be interrupted. What is the best way to do this? Questions:

  1. Would it be best to use Ajax to submit the data via forms so the page doesn't have to be refreshed? I could easily recode the game using JavaScript but I want to do this using PHP session variables if possible to show my PHP skills in my portfolio.

  2. Is it possible to nest functions inside the index function to make this work? I believe this isn't but want to make sure. Even if so I suspect this wouldn't be best practice correct?

2 Answers2

0

That way I can have music play in the background and not be interrupted.

Then you should use AJAX, (it's the ONLY sane way) or as suggested by @BeetleJuice throw WebSockets into the mix :/

You can also remove the process_money method and handle it within the index method, just post the form (with or without AJAX) back to itself. Though if the game gets larger, you may wish you put it in its own method.

Lawrence Cherone
  • 46,049
  • 7
  • 62
  • 106
  • Thank you. Would it make sense to manipulate the session variables in a separate PHP file...like how you would do using an external Javascript file if I didn't care to use the session by using a link tag? – Travis Alexander Terrell Jul 24 '17 at 04:36
  • The session should hold across controllers, and when you use ajax you can update the DOM accordingly based upon its response. It will also allow you to reduce the HMTL by only having one form and get the building value from a `data-building="cave"` property etc, much gained by adding a bit of js. users will like it too ;p – Lawrence Cherone Jul 24 '17 at 04:40
  • Ajax is the best way but not the *only* way to accomplish the quoted segment. – BeetleJuice Jul 24 '17 at 04:44
  • @BeetleJuice whats the other ways? Iframes or additional windows? – Lawrence Cherone Jul 24 '17 at 04:45
0

You're on the right track. If you don't want to trigger a page load and interrupt the music, Ajax is a simple way to update the server.

  1. Get rid of the <form> tags.
  2. Change inputs from type="submit" to type="button"
  3. Add an onclick handler to each button: type="button" onclick="process(this)"
  4. In the process(button){} handler, capture the value: v = button.value (eg: 'cave' or 'farm')
  5. In the process() handler, trigger a new Ajax request that sends the value to the PHP script.
  6. In PHP, if a session doesn't exist, load a blank game. Else, if a location value was sent, update gold and send back the new balance.
  7. JavaScript receives the new balance in the Ajax success callback and updates the game (notifies the user).

By the way there is one problem with your existing code. At the casino, the user loses money only if rand(0,1)===0. This will almost never happen. If you want the user to lose money, say 20% of the time, you would check mt_rand(0,1)<=0.2 (I would switch to mt_rand because until PHP 7.1 rand is seriously flawed

BeetleJuice
  • 39,516
  • 19
  • 105
  • 165